The full name of json (javascript object notation) is javascript object notation, which is a text format for data exchange, not a programming language, for reading structured data. It was proposed by Douglas Crockford in 2001 to replace the cumbersome and cumbersome XML format. This article will introduce the relevant content of JSON in detail
grammar rules
The syntax of JSON can represent the following three types of values
[1] Simple value
Simple values use the same syntax as javascript and can represent strings , numbers , booleans and null in JSON
Strings must be expressed in double quotes , not single quotes. Values must be expressed in decimal , and cannot use NaN and Infinity
[Note] JSON does not support the special value undefined in javascript
//qualified simple value 5 "hello world" true null
// unqualified simple value +0x1 'hello world' undefined NaN Infinity
【2】Object
As a complex data type, an object represents an ordered set of key-value pairs. The value in each key-value pair can be a simple value or a value of a complex data type
JSON has three differences compared to javascript's object literals
1. JSON has no concept of variables
2. In JSON, the key name of the object must be placed in double quotes
3. Because JSON is not a javascript statement, there is no semicolon at the end
[Note] Two properties with the same name should not appear in the same object
//qualified object { "name":"huochai", "age":29, "school":{ "name":"diankeyuan", "location":"beijing" } }
// unqualified object { name: "Zhang San", 'age': 32 }//The attribute name must use double quotes {};//The semicolon at the end is not required { "birthday": new Date('Fri, 26 Aug 2011 07:13:10 GMT'), "getName": function() { return this.name; } } // Cannot use functions and date objects
【3】Array
An array is also a complex data type that represents an ordered list of values that can be accessed by numerical indexing. Array values can also be of any type - simple values, objects or arrays
JSON arrays also have no variables and semicolons. Combining arrays and objects can form more complex data collections.
[Note] A comma cannot be added after the last member of an array or object
JSON object
JSON is popular because JSON data structures can be parsed into useful javascript objects
ECMAScript5 standardizes the behavior of parsing JSON and defines the global object JSON
[Note] IE7 - browser does not support
IE7 - browsers can use JSON by using the json2.js file
JSON objects have two methods: stringify() and parse(). These two methods are used to serialize JavaScript objects to JSON strings and parse JSON strings to native JavaScript values, respectively.
stringify()
The JSON.stringify() method is used to convert a value to a string . The string should conform to JSON format and can be restored by JSON.parse() method
By default, the JSON string output by JSON.stringify() does not include any space characters or indentation
var jsonObj = { "title":"javascript", "group":{ "name":"jia", "tel":12345 } }; //{"title":"javascript","group":{"name":"jia","tel":12345}} JSON.stringify(jsonObj);
specific conversion
JSON.stringify('abc') // ""abc"" JSON.stringify(1) // "1" JSON.stringify(false) // "false" JSON.stringify([]) // "[]" JSON.stringify({}) // "{}" JSON.stringify([1, "false", false])// '[1,"false",false]' JSON.stringify({ name: "Zhang San" })// '{"name": "Zhang San"}'
The stringify() method converts regular expressions and math objects to the string form of an empty object
JSON.stringify(/foo/) // "{}" JSON.stringify(Math) // "{}"
The stringify() method converts date objects and wrapper objects into strings
JSON.stringify(new Boolean(true)) //"true" JSON.stringify(new String('123')) //""123"" JSON.stringify(new Number(1)) //"1" JSON.stringify(new Date()) //""2016-09-20T02:26:38.294Z""
If a member of the object is undefined or a function , the member will be omitted
如果数组的成员是undefined或函数,则这些值被转成null
JSON.stringify({ a: function(){}, b: undefined, c: [ function(){}, undefined ] }); // "{"c":[null,null]}"
如果对象成员或数组成员中出现NaN或Infinity,则这些值被转换成null
console.log(JSON.stringify({ a: NaN, b: Infinity, c: [ NaN,Infinity] })); //{"a":null,"b":null,"c":[null,null]}
JSON.stringify()方法会忽略对象的不可遍历属性
var obj = {}; Object.defineProperties(obj, { 'foo': { value: 1, enumerable: true }, 'bar': { value: 2, enumerable: false } }); JSON.stringify(obj); // {"foo":1}]
参数
JSON.stringify()除了要序列化的javascript对象外,还可以接收另外两个参数,这两个参数用于指定以不同的方式序列化javascript对象。第一个参数是个过滤器,可以是一个数组,也可以是一个函数;第二个参数是一个选项,表示是否在JSON字符串中保留缩进
【数组过滤器】
当stringify()方法的第二个参数是一个数组时,这时相当于实现一个过滤器的功能
【1】过滤器只对对象的第一层属性有效
var jsonObj = { "title":"javascript", "group":{ "a":1 } }; //{"group":{"a":1}} console.log(JSON.stringify(jsonObj,["group","a"]))
【2】过滤器对数组无效
var jsonObj =[1,2]; JSON.stringify(jsonObj,["0"])//"[1,2]"
【函数参数】
stringify()方法的第二个参数也可以是一个函数。传入的函数接收两个参数,属性(键)名和属性值
JSON.stringify({a:1,b:2}, function(key, value){ if (typeof value === "number") { value = 2 * value; } return value; }) // "{"a":2,"b":4}"
属性名只能是字符串,而在值并非键值对儿结构的值时,键名可以是空字符串
这个函数参数会递归处理所有的键
下面代码中,对象o一共会被f函数处理三次。第一次键名为空,键值是整个对象o;第二次键名为a,键值是{b:1};第三次键名为b,键值为1
JSON.stringify({a: {b: 1}}, function (key, value) { console.log("["+ key +"]:" + value); return value; }) // []:[object Object] // [a]:[object Object] // [b]:1 // '{"a":{"b":1}}'
函数返回的值就是相应键的值。如果函数返回了undefined或没有返回值,那么相应的属性会被忽略
JSON.stringify({ a: "abc", b: 123 }, function (key, value) { if (typeof(value) === "string") { return undefined; } return value; }) // '{"b": 123}'
【缩进】
stringify()方法还可以接受第三个参数,用于增加返回的JSON字符串的可读性
如果是数字,表示每个属性前面添加的空格(最多不超过10个)
如果是字符串(不超过10个字符),则该字符串会添加在每行前面
/*"{ "p1": 1, "p2": 2 }"*/ JSON.stringify({ p1: 1, p2: 2 }, null, 2);
//"{"p1":1,"p2":2}" JSON.stringify({ p1: 1, p2: 2 }, null, 0);
/*"{ |-"p1": 1, |-"p2": 2 }"*/ JSON.stringify({ p1:1, p2:2 }, null, '|-');
toJSON()
有时候,JSON.stringify()还是不能满足对某些对象进行自定义序列化的需求。在这些情况下, 可以通过在对象上调用toJSON()方法,返回其自身的JSON数据格式
JSON.stringify({ toJSON: function () { return "Cool" } }) // ""Cool""
var o = { foo: 'foo', toJSON: function() { return 'bar'; } }; JSON.stringify({x: o});// '{"x":"bar"}'
如果toJSON()方法返回undefined,此时如果包含它的对象嵌入在另一个对象中,会导致该对象的值变成null。而如果包含它的对象是顶级对象,结果就是undefined
JSON.stringify({ toJSON: function () { return undefined } }) //undefined
Date对象部署了一个自己的toJSON方法,自动将Date对象转换成日期字符串
JSON.stringify(new Date("2016-08-29")) // "2016-08-29T00:00:00.000Z"
toJSON方法的一个应用是,可以将正则对象自动转为字符串
RegExp.prototype.toJSON =RegExp.prototype.toString; JSON.stringify(/foo/)// ""/foo/""
toJSON()可以作为函数过滤器的补充,因此理解序列化的内部顺序十分重要。假设把一个对象传入JSON.stringify(),序列化该对象的顺序如下
1、如果存在toJSON()方法而且能通过它取得有效的值,则调用该方法。否则,按默认顺序执行序列化
2、如果提供了第二个参数,应用这个函数过滤器。传入函数过滤器的值是第一步返回的值
3、对第二步返回的每个值进行相应的序列化
4、如果提供了第三个参数,执行相应的格式化
parse()
JSON.parse方法用于将JSON字符串转化成对象
JSON.parse('{}') // {} JSON.parse('true') // true JSON.parse('"foo"') // "foo" JSON.parse('[1, 5, "false"]') // [1, 5, "false"] JSON.parse('null') // null var o = JSON.parse('{"name": "张三"}'); o.name // 张三
如果传入的字符串不是有效的JSON格式,JSON.parse方法将报错
//Uncaught SyntaxError: Unexpected token u in JSON at position 0(…) JSON.parse("'String'") //Uncaught SyntaxError: Unexpected token u in JSON at position 0(…) JSON.parse("undefined")
JSON.parse()方法也可以接收一个函数参数,在每个键值对儿上调用,这个函数被称为还原函数(reviver)。该函数接收两个参数,一个键和一个值,返回一个值
如果还原函数返回undefined,则表示要从结果中删除相应的键;如果返回其他值,则将该值插入到结果中
var o = JSON.parse('{"a":1,"b":2}', function(key, value) { if (key === ''){ return value; } if (key === 'a') { return value + 10; } }); o.a // 11 o.b // undefined
在将日期字符串转换为Date对象时,经常要用到还原函数
var book = { "title": "javascript", "date": new Date(2016,9,1) } var jsonStr = JSON.stringify(book); //'{"title":"javascript","date":"2016-09-30T16:00:00.000Z"}'' console.log(jsonStr) var bookCopy = JSON.parse(jsonStr,function(key,value){ if(key == 'date'){ return new Date(value); } return value; }) console.log(bookCopy.date.getFullYear());//2016
eval()
Actually, eval() is similar to JSON.parse() method, which can convert json string to json object
eval('(' + '{"a":1}'+')').a;//1 JSON.parse('{"a":1}').a;//1
However, eval() can execute code that does not conform to JSON format and may contain malicious code
eval('(' + '{"a":alert(1)}'+')').a;//Pop up 1 JSON.parse('{"a":alert(1)}').a;//Error
So, try to use eval() as little as possible