16

I have tried to convert a JS object into JSON.

JSON.stringify({a:1, toJSON: function(){}})

Native JSON stringify is not working as expected. JSON stringify executes toJSON function in JS object internally. I have overwritten native code as follows,

// Adding try catch for non JSON support browsers.
try{
 _jsonStringify = JSON.stringify;
 JSON.stringify = function(object){
    var fnCopy = object.toJSON; 
    object.toJSON = undefined;
    var result =  _jsonStringify(object);
    object.toJSON = fnCopy;
    return result;      
 };
}catch(e){}

It is working fine. is there any other better way to do this?. is there any specific reason in native code execute toJSON function in input object?

3
  • You should use json2.js for browsers that do not support JSON.stringify Commented May 27, 2014 at 19:32
  • My questions are still pending ('is there any specific reason in native code execute toJSON function in input object?`). If anybody know reason, please update this thread. Commented May 27, 2014 at 20:30
  • It's so you can customize the serialization. I've updated my answer with an example for you. Commented May 27, 2014 at 20:55

3 Answers 3

15

This is because JSON.stringify will return the return value of the toJSON function if it exists (Source).

For example:

JSON.stringify({a:1, toJSON: function(){ return "a"; }});

Will return:

"a"

This behaviour is described on MDN. The reason for this is so that you can customize the behaviour of the serialization. For example, say I only want to serialize the IDs of the Animal class in this example. I could do the following:

var Animal = function(id, name) {
    this.AnimalID = id;
    this.Name     = name;
};

Animal.prototype.toJSON = function() {
    return this.AnimalID;
};

var animals = [];

animals.push(new Animal(1, "Giraffe"));
animals.push(new Animal(2, "Kangaroo"));

JSON.stringify(animals); // Outputs [1,2]

If you do not want this behaviour then your current method works well; however, I would recommend not overwriting the behaviour of JSON.stringify, but rather name your method something else. An external library might be using the toJSON function in an object and it could lead to unexpected results.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks @dhsto, I think I have to go through the code in github.com/douglascrockford/JSON-js/blob/master/json2.js (link in your answer).
@hilarudeens I wouldn't bother if I were you. I would just use the method you use in your question, but name your new function something else other than JSON.stringify.
I agree. Override native is not good practice. Hopefully, this is going to be good starting point for other developer who wants to drill down this further.
Nice answer. I agree.
0

The reason the native JSON.stringify doesn't work is because it can't stringify functions. By setting the only function, toJSON, to undefined, JSON.stringify returns the proper value. See this question for more details: JSON.stringify function

If you're trying to remove functions entirely, you can do this:

JSON.stringify(object, function(key, value) {
  if (typeof value === "function") {
    return undefined;
  }
  return value;
});

2 Comments

Thanks dude, However my question is different. On executing JSON.stringify({a:1, toJSON: function(){}}), I am expecting {"a":1}.
It is not working. I have tried JSON.stringify({a:1, toJSON: function(){ return "Hello"; }}, function(key, value) { debugger; if (typeof value === "function") { return undefined; } return value; }); in chrome. Have you run this code?
-3

The JSON.stringify function is usually invoked with one parameter, which is the object you want to serialize to JSON string. I believe there's a second optional parameter, which is a function that replaces one or more properties' way of serialization.

However, you should not add a function as a second property of your object!

When trying the following in Chrome's console:

JSON.stringify({a:1,b:'hello'})

This is the result:

"{"a":1,"b":"hello"}"

1 Comment

Sorry my question is different. On executing JSON.stringify({a:1, toJSON: function(){}}), I am expecting {"a":1} which is not working.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.