/*=== basic reviver reviver called name: val: foo holder: [object Object] {"":"foo"} ===*/ /* Basic reviver test. */ print('basic reviver'); function basicReviverTest() { var v; function reviver(name, val) { var holder = this; print('reviver called'); print('name:', name); print('val:', val); print('holder:', holder); print(JSON.stringify(holder)); } v = JSON.parse('"foo"', reviver); } try { basicReviverTest(); } catch (e) { print(e.name); } /*=== complex reviver test {"k_null":null, "k_true":true, "k_false":false, "k_num":123, "k_str":"str", "k_arr":[1,2], "k_obj":{"foo":1,"bar":2}} reviver: json(name)="k_null", json(val)=null, json(holder)={"k_null":null,"k_true":true,"k_false":false,"k_num":123,"k_str":"str","k_arr":[1,2],"k_obj":{"foo":1,"bar":2}} reviver: json(name)="k_true", json(val)=true, json(holder)={"k_null":null,"k_true":true,"k_false":false,"k_num":123,"k_str":"str","k_arr":[1,2],"k_obj":{"foo":1,"bar":2}} reviver: json(name)="k_false", json(val)=false, json(holder)={"k_null":null,"k_true":true,"k_false":false,"k_num":123,"k_str":"str","k_arr":[1,2],"k_obj":{"foo":1,"bar":2}} reviver: json(name)="k_num", json(val)=123, json(holder)={"k_null":null,"k_true":true,"k_false":false,"k_num":123,"k_str":"str","k_arr":[1,2],"k_obj":{"foo":1,"bar":2}} reviver: json(name)="k_str", json(val)="str", json(holder)={"k_null":null,"k_true":true,"k_false":false,"k_num":123,"k_str":"str","k_arr":[1,2],"k_obj":{"foo":1,"bar":2}} reviver: json(name)="0", json(val)=1, json(holder)=[1,2] reviver: json(name)="1", json(val)=2, json(holder)=[1,2] reviver: json(name)="k_arr", json(val)=[1,2], json(holder)={"k_null":null,"k_true":true,"k_false":false,"k_num":123,"k_str":"str","k_arr":[1,2],"k_obj":{"foo":1,"bar":2}} reviver: json(name)="foo", json(val)=1, json(holder)={"foo":1,"bar":2} reviver: json(name)="bar", json(val)=2, json(holder)={"foo":1,"bar":2} reviver: json(name)="k_obj", json(val)={"foo":1,"bar":2}, json(holder)={"k_null":null,"k_true":true,"k_false":false,"k_num":123,"k_str":"str","k_arr":[1,2],"k_obj":{"foo":1,"bar":2}} reviver: json(name)="", json(val)={"k_null":null,"k_true":true,"k_false":false,"k_num":123,"k_str":"str","k_arr":[1,2],"k_obj":{"foo":1,"bar":2}}, json(holder)={"":{"k_null":null,"k_true":true,"k_false":false,"k_num":123,"k_str":"str","k_arr":[1,2],"k_obj":{"foo":1,"bar":2}}} {"k_null":null,"k_true":true,"k_false":false,"k_num":123,"k_str":"str","k_arr":[1,2],"k_obj":{"foo":1,"bar":2}} ===*/ /* A more complex reviver test; no changes are made, just check the * call order and arguments. */ print('complex reviver test'); function complexReviverTest() { var txt; var v; function reviver(name, val) { var holder = this; print('reviver: json(name)=' + JSON.stringify(name) + ', json(val)=' + JSON.stringify(val) + ', json(holder)=' + JSON.stringify(holder)); return val; } txt = '{"k_null":null, "k_true":true, "k_false":false, ' + '"k_num":123, "k_str":"str", "k_arr":[1,2], ' + '"k_obj":{"foo":1,"bar":2}}'; print(txt); v = JSON.parse(txt, reviver); print(JSON.stringify(v)); } try { complexReviverTest(); } catch (e) { print(e.name, e); } /*=== reviver deletion test {"k_null":null, "k_true":true, "k_false":false, "k_num":123, "k_str":"str", "k_arr":[1,2], "k_obj":{"foo":1,"bar":2}} reviver: json(name)="k_null", json(val)=null, json(holder)={"k_null":null,"k_true":true,"k_false":false,"k_num":123,"k_str":"str","k_arr":[1,2],"k_obj":{"foo":1,"bar":2}} reviver: json(name)="k_true", json(val)=true, json(holder)={"k_null":null,"k_true":true,"k_false":false,"k_num":123,"k_str":"str","k_arr":[1,2],"k_obj":{"foo":1,"bar":2}} reviver: json(name)="k_false", json(val)=false, json(holder)={"k_null":null,"k_false":false,"k_num":123,"k_str":"str","k_arr":[1,2],"k_obj":{"foo":1,"bar":2}} reviver: json(name)="k_num", json(val)=123, json(holder)={"k_null":null,"k_false":false,"k_num":123,"k_str":"str","k_arr":[1,2],"k_obj":{"foo":1,"bar":2}} reviver: json(name)="k_str", json(val)="str", json(holder)={"k_null":null,"k_false":false,"k_num":123,"k_str":"str","k_arr":[1,2],"k_obj":{"foo":1,"bar":2}} reviver: json(name)="0", json(val)=1, json(holder)=[1,2] reviver: json(name)="1", json(val)=2, json(holder)=[1,2] reviver: json(name)="k_arr", json(val)=[1,2], json(holder)={"k_null":null,"k_false":false,"k_num":123,"k_str":"str","k_arr":[1,2],"k_obj":{"foo":1,"bar":2}} reviver: json(name)="foo", json(val)=1, json(holder)={"foo":1,"bar":2} reviver: json(name)="bar", json(val)=2, json(holder)={"foo":1,"bar":2} reviver: json(name)="k_obj", json(val)={"foo":1,"bar":2}, json(holder)={"k_null":null,"k_false":false,"k_num":123,"k_str":"str","k_obj":{"foo":1,"bar":2}} reviver: json(name)="", json(val)={"k_null":null,"k_false":false,"k_num":123,"k_str":"str","k_obj":{"foo":1,"bar":2}}, json(holder)={"":{"k_null":null,"k_false":false,"k_num":123,"k_str":"str","k_obj":{"foo":1,"bar":2}}} {"k_null":null,"k_false":false,"k_num":123,"k_str":"str","k_obj":{"foo":1,"bar":2}} ===*/ /* Reviver deletion test. */ print('reviver deletion test'); function reviverDeletionTest() { var txt; var v; function reviver(name, val) { var holder = this; print('reviver: json(name)=' + JSON.stringify(name) + ', json(val)=' + JSON.stringify(val) + ', json(holder)=' + JSON.stringify(holder)); // delete k_arr and k_true if (name === 'k_arr' || name === 'k_true') { return; } return val; } txt = '{"k_null":null, "k_true":true, "k_false":false, ' + '"k_num":123, "k_str":"str", "k_arr":[1,2], ' + '"k_obj":{"foo":1,"bar":2}}'; print(txt); v = JSON.parse(txt, reviver); print(JSON.stringify(v)); } try { reviverDeletionTest(); } catch (e) { print(e.name); } /*=== reviver replacement test {"k_null":null, "k_true":true, "k_false":false, "k_num":123, "k_str":"str", "k_arr":[1,2], "k_obj":{"foo":1,"bar":2}} reviver: json(name)="k_null", json(val)=null, json(holder)={"k_null":null,"k_true":true,"k_false":false,"k_num":123,"k_str":"str","k_arr":[1,2],"k_obj":{"foo":1,"bar":2}} reviver: json(name)="k_true", json(val)=true, json(holder)={"k_null":null,"k_true":true,"k_false":false,"k_num":123,"k_str":"str","k_arr":[1,2],"k_obj":{"foo":1,"bar":2}} reviver: json(name)="k_false", json(val)=false, json(holder)={"k_null":null,"k_true":[3,2,1],"k_false":false,"k_num":123,"k_str":"str","k_arr":[1,2],"k_obj":{"foo":1,"bar":2}} reviver: json(name)="k_num", json(val)=123, json(holder)={"k_null":null,"k_true":[3,2,1],"k_false":false,"k_num":123,"k_str":"str","k_arr":[1,2],"k_obj":{"foo":1,"bar":2}} reviver: json(name)="k_str", json(val)="str", json(holder)={"k_null":null,"k_true":[3,2,1],"k_false":false,"k_num":123,"k_str":"str","k_arr":[1,2],"k_obj":{"foo":1,"bar":2}} reviver: json(name)="0", json(val)=1, json(holder)=[1,2] reviver: json(name)="1", json(val)=2, json(holder)=[1,2] reviver: json(name)="k_arr", json(val)=[1,2], json(holder)={"k_null":null,"k_true":[3,2,1],"k_false":false,"k_num":123,"k_str":"str","k_arr":[1,2],"k_obj":{"foo":1,"bar":2}} reviver: json(name)="foo", json(val)=1, json(holder)={"foo":1,"bar":2} reviver: json(name)="bar", json(val)=2, json(holder)={"foo":1,"bar":2} reviver: json(name)="k_obj", json(val)={"foo":1,"bar":2}, json(holder)={"k_null":null,"k_true":[3,2,1],"k_false":false,"k_num":123,"k_str":"str","k_arr":{"foo":"foo","bar":"bar"},"k_obj":{"foo":1,"bar":2}} reviver: json(name)="", json(val)={"k_null":null,"k_true":[3,2,1],"k_false":false,"k_num":123,"k_str":"str","k_arr":{"foo":"foo","bar":"bar"},"k_obj":{"foo":1,"bar":2}}, json(holder)={"":{"k_null":null,"k_true":[3,2,1],"k_false":false,"k_num":123,"k_str":"str","k_arr":{"foo":"foo","bar":"bar"},"k_obj":{"foo":1,"bar":2}}} {"k_null":null,"k_true":[3,2,1],"k_false":false,"k_num":123,"k_str":"str","k_arr":{"foo":"foo","bar":"bar"},"k_obj":{"foo":1,"bar":2}} ===*/ /* Reviver replacement test. * * In particular, test whether or not reviver will walk through the returned; * it should not. */ print('reviver replacement test'); function reviverReplacementTest() { var txt; var v; function reviver(name, val) { var holder = this; print('reviver: json(name)=' + JSON.stringify(name) + ', json(val)=' + JSON.stringify(val) + ', json(holder)=' + JSON.stringify(holder)); // replace k_true with [3,2,1] and k_arr with {foo:'foo',bar:'bar} if (name === 'k_arr') { return { foo: 'foo', bar: 'bar' }; } else if (name === 'k_true') { return [ 3, 2, 1 ]; } else { return val; } } txt = '{"k_null":null, "k_true":true, "k_false":false, ' + '"k_num":123, "k_str":"str", "k_arr":[1,2], ' + '"k_obj":{"foo":1,"bar":2}}'; print(txt); v = JSON.parse(txt, reviver); print(JSON.stringify(v)); } try { reviverReplacementTest(); } catch (e) { print(e.name); } /*=== reviver object identity {"foo":1,"bar":2} reviver: json(name)="foo", json(val)=1, json(holder)={"foo":1,"bar":2} reviver: json(name)="bar", json(val)=2, json(holder)={"foo":{},"bar":2} reviver: json(name)="", json(val)={"foo":{},"bar":{}}, json(holder)={"":{"foo":{},"bar":{}}} {"foo":{},"bar":{}} true true true ===*/ /* Check that replacement values are used as is. In particular, * returning the same object retains object identity in the result. */ print('reviver object identity'); function reviverObjectIdentityTest() { var txt; var v; var repl_value = {}; // test this identity function reviver(name, val) { var holder = this; print('reviver: json(name)=' + JSON.stringify(name) + ', json(val)=' + JSON.stringify(val) + ', json(holder)=' + JSON.stringify(holder)); if (name === 'foo' || name === 'bar') { return repl_value; } else { return val; } } txt = '{"foo":1,"bar":2}'; print(txt); v = JSON.parse(txt, reviver); print(JSON.stringify(v)); print(v.foo === repl_value); print(v.bar === repl_value); print(v.foo === v.bar); } try { reviverObjectIdentityTest(); } catch (e) { print(e.name); } /*=== reviver name type test {"foo":1,"bar":[2,3]} object string number object string number object string number object string object object string object {"foo":1,"bar":[2,3]} ===*/ /* Reviver 'name' argument is a string key of an object, or a string * coercion (ToString(arr_index)) of an array index. * * (Rhino uses a numeric array index key.) */ print('reviver name type test'); function reviverNameTypeTest() { function reviver(name, val) { print(typeof this, typeof name, typeof val); return val; } txt = '{"foo":1,"bar":[2,3]}'; print(txt); v = JSON.parse(txt, reviver); print(JSON.stringify(v)); } try { reviverNameTypeTest(); } catch (e) { print(e.name); } /*=== invalid revivers {"foo":1,"bar":2} {"foo":1,"bar":2} {"foo":1,"bar":2} {"foo":1,"bar":2} {"foo":1,"bar":2} {"foo":1,"bar":2} {"foo":1,"bar":2} {"foo":1,"bar":2} {"foo":1,"bar":2} ===*/ /* Reviver must callable; other values are ignored silently. */ print('invalid revivers'); function testInvalidRevivers() { var v; // base case v = JSON.parse('{"foo":1,"bar":2}'); print(JSON.stringify(v)); v = JSON.parse('{"foo":1,"bar":2}', undefined); print(JSON.stringify(v)); v = JSON.parse('{"foo":1,"bar":2}', null); print(JSON.stringify(v)); v = JSON.parse('{"foo":1,"bar":2}', true); print(JSON.stringify(v)); v = JSON.parse('{"foo":1,"bar":2}', false); print(JSON.stringify(v)); v = JSON.parse('{"foo":1,"bar":2}', 1.23); print(JSON.stringify(v)); v = JSON.parse('{"foo":1,"bar":2}', 'foo'); print(JSON.stringify(v)); v = JSON.parse('{"foo":1,"bar":2}', []); print(JSON.stringify(v)); v = JSON.parse('{"foo":1,"bar":2}', {}); print(JSON.stringify(v)); } try { testInvalidRevivers(); } catch (e) { print(e.name); }