ZH奶酪:JavaScript中的JSON.stringify() and JSON.parse()

 


JSON.stringify()

JSON.stringify()可以将任意的JavaScript值序列化成JSON字符串。

语法

JSON.stringify(value[, replacer [, space]])

其中

value:将要序列化成JSON字符串的JavaScript值;

replacer(optional):

  该参数可以是函数,在序列化过程中,被序列化的值的每个属性都会经过该函数的转换和处理;

  该参数可以是数组,在序列化过程中,只有包含在这个数组中的属性名才会被序列化到最终JSON字符串中;

space(optional):

  指定缩进用的空白字符串,用于美化输出;

注意事项:  

  • 非数组对象的属性不能保证以特定的顺序出现在序列化后的字符串中。
  • 布尔值、数字、字符串的包装对象在序列化过程中会自动转换成对应的原始值。
  • undefined、任意的函数以及 symbol 值,在序列化过程中会被忽略(出现在非数组对象的属性值中时)或者被转换成 null(出现在数组中时)。
  • 所有以 symbol 为属性键的属性都会被完全忽略掉,即便 replacer 参数中强制指定包含了它们。
 1 JSON.stringify({});                        // '{}'
 2 JSON.stringify(true);                      // 'true'
 3 JSON.stringify("foo");                     // '"foo"'
 4 JSON.stringify([1, "false", false]);       // '[1,"false",false]'
 5 JSON.stringify({ x: 5 });                  // '{"x":5}'
 6 
 7 JSON.stringify({x: 5, y: 6});              
 8 // '{"x":5,"y":6}' 或者 '{"y":6,"x":5}' 都可能
 9 JSON.stringify([new Number(1), new String("false"), new Boolean(false)]); 
10 // '[1,"false",false]'
11 JSON.stringify({x: undefined, y: Object, z: Symbol("")}); 
12 // '{}'
13 JSON.stringify([undefined, Object, Symbol("")]);          
14 // '[null,null,null]' 
15 JSON.stringify({[Symbol("foo")]: "foo"});                 
16 // '{}'
17 JSON.stringify({[Symbol.for("foo")]: "foo"}, [Symbol.for("foo")]);
18 // '{}'
19 JSON.stringify({[Symbol.for("foo")]: "foo"}, function (k, v) {
20   if (typeof k === "symbol"){
21     return "a symbol";
22   }
23 });
24 // '{}'

replacer参数

 replacer函数可以是一个函数或者是一个数组。

  如果四号函数,则该函数会被传入两个参数,分别是当前正在被字符串化的键值对的键和值。初始化时,一个默认的键值对会

1 function censor(key, value) {
2   if (typeof(value) == "string") {
3     return undefined;
4   }
5   return value;
6 }
7 
8 var foo = {foundation: "Mozilla", model: "box", week: 45, transport: "car", month: 7};
9 var jsonString = JSON.stringify(foo, censor);

 jsonString 的新值为{"week":45,"month":7}.

space参数

space参数用来控制结果字符串里面的间距。

  如果是一个数字,则在序列化时,每一级别会比上一级别缩进多这个数字值的空格(最多10个空格);

  如果是一个字符串,则每一级别会比上一级别多缩进一个该字符串(或前10个字符);

1 JSON.stringify({ a: 2 }, null, " ");   // '{\n "a": 2\n}'

  使用制表符\t来缩进:

1 JSON.stringify({ uno: 1, dos : 2 }, null, '\t')
2 // '{            \
3 //     "uno": 1, \
4 //     "dos": 2  \
5 // }'

toJSON方法

  如果一个被序列化的对象拥有toJSON方法,那么该toJSON方法就会覆盖该对象默认的序列化行为(不是那个对象被序列化,而是调用toJSON方法后的返回值会被序列化),例如:

1 var obj = {
2   foo: 'foo',
3   toJSON: function () {
4     return 'bar';
5   }
6 };
7 JSON.stringify(obj);      // '"bar"'
8 JSON.stringify({x: obj}); // '{"x":"bar"}'

使用JSON.stringify结合localStorage的例子

一些时候,你想存储用户创建的一个对象,并且,即使在浏览器被关闭后仍能恢复该对象。下面的例子是JSON.stringify适用于这种情形的一个样板:

 1 // 创建一个示例数据
 2 var session = {
 3     'screens' : [],
 4     'state' : true
 5 };
 6 session.screens.push({"name":"screenA", "width":450, "height":250});
 7 session.screens.push({"name":"screenB", "width":650, "height":350});
 8 session.screens.push({"name":"screenC", "width":750, "height":120});
 9 session.screens.push({"name":"screenD", "width":250, "height":60});
10 session.screens.push({"name":"screenE", "width":390, "height":120});
11 session.screens.push({"name":"screenF", "width":1240, "height":650});
12 
13 // 使用 JSON.stringify 转换为 JSON 字符串
14 // 然后使用 localStorage 保存在 session 名称里
15 localStorage.setItem('session', JSON.stringify(session));
16 
17 // 然后是如何转换通过 JSON.stringify 生成的字符串,该字符串以 JSON 格式保存在 localStorage 里
18 var restoredSession = JSON.parse(localStorage.getItem('session'));
19 
20 // 现在 restoredSession 包含了保存在 localStorage 里的对象
21 console.log(restoredSession);

JSON.parse()

JSON.parse()方法可以将一个JSON字符串解析成为一个JavaScript值。在解析过程中,可以选择性的修改某些属性的原石值。

语法:

1 JSON.parse(text[, reviver])

其中,

text:

  要解析的JSON字符串;

reviver(optional):

  用来转换解析出的属性值的函数;

返回值:

  从text字符串解析出的一个JavaScript值;

异常:

如果被解析的JSON字符串包含语法错误,则会抛出SyntaxError异常。

示例:使用JSON.parse()

1 JSON.parse('{}');              // {}
2 JSON.parse('true');            // true
3 JSON.parse('"foo"');           // "foo"
4 JSON.parse('[1, 5, "false"]'); // [1, 5, "false"]
5 JSON.parse('null');            // null

使用reviver函数

  如果制订了reviver函数,则解析出的JavaScript值会经过一次转换后才将被最终返回。

  具体过程是这样的:

  解析值本身及其所包含的所有属性,会按照一定的顺序(从内向外)分别调用reviver函数;

  在调用过程中,当前属性所属的对象会作为this值,当前属性名和属性值会分别作为第一个和第二个参数传入reviver中;

  如果reviver返回undefined,则当前属性会从所属对象中删除;

  如果返回了其他值,则返回的值会成为当前属性新的属性值;

  当遍历到最顶层的值时,传入reviver函数的参数回事空字符串和当前的解析值,当前的this值回事{“”:修改过的解析值},在编写reviver函数时,要注意到这个特例。

 1 JSON.parse('{"p": 5}', function (k, v) {
 2     if(k === '') return v;     // 如果到了最顶层,则直接返回属性值,
 3     return v * 2;              // 否则将属性值变为原来的 2 倍。
 4 });                            // { p: 10 }
 5 
 6 JSON.parse('{"1": 1, "2": 2,"3": {"4": 4, "5": {"6": 6}}}', function (k, v) {
 7     console.log(k); // 输出当前的属性名,从而得知遍历顺序是从内向外的,
 8                     // 最后一个属性名会是个空字符串。
 9     return v;       // 返回原始属性值,相当于没有传递 reviver 参数。
10 });
11 
12 // 1
13 // 2
14 // 4
15 // 6
16 // 5
17 // 3 
18 // ""

JSON.parse()不允许逗号结尾

1 // both will throw a SyntaxError
2 JSON.parse("[1, 2, 3, 4, ]");
3 JSON.parse("{ \"foo\" : 1, }");
posted @ 2015-06-03 16:09  ZH奶酪  阅读(668)  评论(0编辑  收藏  举报