JSON.stringify and non associative array - javascript

I want to serialize in json a non associative array and the output is quite disturbing
JSON.stringify([1]);
// Expected : "[1]"
Output : "\"[1]\""
It treats the array as a string, what am i missing ?
I'm using Chrome Version 29.0.1547.65

The issue you are seeing is because of an Array.prototype.toJSON method that has been defined incorrectly with respect to the semantics of JSON.stringify. See below:
From: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
toJSON behavior
If an object being stringified has a property named toJSON whose value
is a function, then the toJSON method customizes JSON stringification
behavior: instead of the object being serialized, the value returned
by the toJSON method when called will be serialized.
When an object has a toJSON method the result of that method will be stringified in its place. If the toJSON method is defined as a stringification then the object will be double stringified.
The only work-around I am aware of is to remove the method or to implement your own stringify() method with different semantics than the built-in.
If you can, simply remove the method from Array.prototype. If you are concerned this will break other functionality on the page then you need to remove it, stringify, then restore it.
function myStringify( o ) {
var temp = Array.prototype.toJSON;
delete Array.prototype.toJSON;
var result = JSON.stringify(o);
Array.prototype.toJSON = temp;
return result;
}

Related

JSON stringify outputs empty object for not empty object [duplicate]

I need to convert to a JSON value the result of a DOMRect object returned by Element.getBoundingClientRect()
Here an example:
http://jsfiddle.net/5vs6x6fc/2/
When using JSON.stringify() it returns {}, I need the JSON value instead.
I would like to know:
Why is that?
What could be a possible solution alternative to looping to the property of the returned object r ex: for (var property in r){}
Notes: I am targeting Chrome.
Bounding rect only contains "virtual" properties. If you
console.log(Object.getOwnPropertyNames(r));
// or
console.log(Object.keys(r));
you'll get an empty list. JSON.stringify() depends on Object.keys(r) (see comments below) and thus returns an empty object literal.
Your loop-based approach seems to be a feasible solution to this problem.

JSON Object not fully converts to String?

I am facing an issue that JSON.stringify not stringifies all the keys in a JSON Object.
ie. window.performance.getEntries()[0] contains around 17 keys. But on converting to a string, the result contains only 4 keys.
How can I convert all the keys in window.performance.getEntries()[0]?
I want the complete string output of window.performance.getEntries() which is an array and I used JSON.stringify(window.performance.getEntries()).
Thanks in advance..
window.performance seems to have is own toJSON-function and so can determine what will be stringified. Here is a answer and a work around to your question from a similiar question: https://stackoverflow.com/a/20511811/3400898
"If the stringify method sees an object that contains a toJSON method, it calls that method, and stringifies the value returned. This allows an object to determine its own JSON representation."
As other stated it is because there is a toJSON method defined. Basically you need to loop over every index of the array and than every property in the object.
var adjusted = window.performance.getEntries().map( function (result) {
var temp = {}, key;
for (key in result) if (key!=="toJSON") temp[key]=result[key];
return temp;
});
console.log(JSON.stringify(adjusted[0]));
The simplified solution for this problem which I found is
var jsonArray = $.map(performance.getEntries(),function(jsonObj){
var obj = $.extend({},jsonObj);
delete obj.toJSON;
return obj;
});
JSON.stringify(jsonArray);

What does 'symbol-keyed' mean in `JSON.stringify`

There is a Object generated by Node.js, it looks like this when I use console.log:
{ dataValues: { a: 1, b: 2 }, fn1: function(){}, fn2: function(){} }
when I use JSON.stringify, it return this string:
{"a":1,"b":1}
I checked the mozilla developer center and found this:
All symbol-keyed properties will be completely ignored, even when using the replacer function.
I think the 'dataValues' must be the 'symbol-keyed' property, but what does 'symbol-keyed' mean?
btw, I use the sequelizejs ORM lib to generate this object.
I found the reason finally in the same page:
If an object being stringified has a property named toJSON whose value is a function, then the toJSON method customizes JSON stringification behavior: instead of the object being serialized, the value returned by the toJSON method when called will be serialized.
It runs on browser normally.
Here is the jsfiddle to run it like I asked.
Code:
function test(data) {
for(var key in data){
this[key] = data[key];
}
}
test.prototype.toJSON = function(){
return this.dataValues;
}
var a = new test({dataValues: {a:1, b:2}});
console.log(a);//the instance
console.log(JSON.stringify(a));//{"a":1,"b":1}
Nah, the relevant part to your issue is this blurb:
If undefined, a function, or a symbol is encountered during conversion
it is either omitted (when it is found in an object) or censored to
null (when it is found in an array).
So in other words, if your JSON object contains functions, they are omitted during the JSON.stringify process.
"symbol-keyed" refers to a new primitive type introduced in ecmascript6. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof for more info.
This is an example of a "symbol-keyed" property:
{[Symbol("foo")]: "foo"}
Reference for JavaScript Symbol: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol

JavaScript array of objects - 0th element undefined but stringify shows objects

I am pulling an object from backbone.js and when I stringify the object I see string literal
'[{"Name":"Testname","Address":"Testaddress","id":"444444444444444"}]'
However, when I assign the non-serialized object to a variable and try to access the 0th element, I get undefined. I would expect to get object
{"Name":"Testname","Address":"Testaddress","id":"444444444444444"}
Is JavaScript not treating
[{"Name":"Testname","Address":"Testaddress","id":"444444444444444"}]
as an indexed array of objects?
To access elements of Backbone.Collection by index, use the Collection#at method:
var first = collection.at(0);
Alternatively, you can use the Collection#first method, which is actually part of the underscore library, but is proxied to Backbone collections for syntactic sugar:
var first = collection.first();
The reason you're seeing the array representation in the serialized JSON is that by convention JSON.stringify looks for a method called toJSON on the object you give to it to stringify, and if one is found, the return value of that method will be used instead. The implementation of Collection#toJSON returns a clone of the collection's internal array of models, and thus the JSON output is an array.
Just tried
var arr = JSON.parse( '[{"Name":"Testname","Address":"Testaddress","id":"444444444444444"}]' );
and
console.log( arr[0] ); // => object
What you've described should work.

Dynamically Reading Array Values form a JSON Object

I am working on a function that accepts a JSON object as a parameter. Each property of the object passed in will be an array. I need to determine the length of each of these arrays.
What I won't know in advance are: the names of the properties, or how many properties there are.
How can I determine the length of each array? Again, I can't refer to any of the properties/keys explicitly because I won't know their names ahead of time. How do I reference each unknown property as an array?
Thank you in advance,
-RS
You can iterate over the object using a for...in loop to access each property.
for (var key in myObject) {
// Check to make sure the property is not part of the `Object` prototype (eg. toString)
if (myObject.hasOwnProperty(key)) {
console.log(key, myObject[key].length);
}
}
In the above example, we iterate over the properties of the object myObject and we log out their length values (assuming they are all arrays).
If by "JSON object" you mean that it is a string of JSON, you can first parse myObject into a true object by using myObject = JSON.parse(myObject) (which works in modern browsers) or myObject = eval("(" + myOjbect + ")") which is considered unsafe (but works in all browsers). After parsing, you may use the above technique to fine array lengths.
Note: Since you updated the post to specify that the object is JSON, you may not need the hasOwnProperty check, but it is safer to always use this test.
Use JSON.parse to convert JSON data to JS Objects, and then you can use Array's length etc properties.
var myObject = JSON.parse(myJSONtext, reviver);
JSON Reference: http://www.json.org/js.html

Categories