/*=== {"foo":1,"bar":"bar/toJSON"} {"foo":1,"bar":"bar/toJSON","quux":{"toJSON":123},"quuux":{"toJSON":{"foo":"not callable"}},"quuuux":{"toJSON":["not callable"]}} Error quuux/toJSON error {"foo":1,"bar":"bar/toJSON","quux":{"toJSON":123},"quuux":"2012-01-02T03:04:05.006Z"} {"foo":1,"bar":"bar/toJSON","quux":{"toJSON":123},"quuux":"inherited toJSON"} ===*/ /* Any Object values with a callable toJSON() property will get called, * and the return value of toJSON() replaces the value to be serialized. * * If toJSON property exists but is not callable, it is ignored. * If toJSON() throws an error, serialization stops with the error. */ function toJsonPropertyTest1() { var obj = { foo: 1, bar: { toJSON: function() { return 'bar/toJSON'; } } }; // toJSON is called print(JSON.stringify(obj)); } function toJsonPropertyTest2() { var obj = { foo: 1, bar: { toJSON: function() { return 'bar/toJSON'; } }, quux: { toJSON: 123 }, quuux: { toJSON: { foo: 'not callable' } }, quuuux: { toJSON: [ 'not callable' ] }, }; // toJSON properties are not callable, and are ignored silently print(JSON.stringify(obj)); } function toJsonPropertyTest3() { var obj = { foo: 1, bar: { toJSON: function() { return 'bar/toJSON'; } }, quux: { toJSON: 123 }, quuux: { toJSON: function() { throw new Error('quuux/toJSON error'); } } }; try { print(JSON.stringify(obj)); } catch (e) { // FIXME: here we assume that message is intact print(e.name, e.message); } } function toJsonPropertyTest4() { var obj = { foo: 1, bar: { toJSON: function() { return 'bar/toJSON'; } }, quux: { toJSON: 123 }, quuux: new Date(Date.parse('2012-01-02T03:04:05.006Z')) }; // Date.prototype.toJSON() ultimately calls Date.prototype.toISOString() // which has an exact output format print(JSON.stringify(obj)); } function toJsonPropertyTest5() { function F() { } F.prototype = { toJSON: function() { return 'inherited toJSON'; } }; var obj = { foo: 1, bar: { toJSON: function() { return 'bar/toJSON'; } }, quux: { toJSON: 123 }, quuux: new F() }; // toJSON() can be inherited print(JSON.stringify(obj)); } try { toJsonPropertyTest1(); toJsonPropertyTest2(); toJsonPropertyTest3(); toJsonPropertyTest4(); toJsonPropertyTest5(); } catch (e) { print(e.name); }