JSON: If you're willing to peel my heart layer by layer, you'll find... the water is deep here - a deep understanding of JSON

Let's first look at the problem of serializing a common JS object in JS into a JSON string. Excuse JSON.stringifyme, what is the string after the following JS object is passed? Don't rush to copy and paste it to the console, first open a code editor or paper, write and read, and then compare your console output carefully. If there is any mistake, remember to read the full text and comment, haha.

var friend={
	firstName: 'Good',
	'lastName': 'Man',
	'address': undefined,
	'phone': ["1234567",undefined],
	'fullName': function(){
		return this.firstName + ' ' + this.lastName;
	}
};

JSON.stringify(friend);//这一行返回什么呢?

The second question, if I want to change the name of this 'friend' into uppercase letters in the final JSON string, that is, change "Good" to "GOOD" and "Man" to "MAN", then I can How to do it?

Based on the above two questions, let's go back to the source and ask, what exactly is JSON? Why is JSON all about easy data exchange? Difference between JSON and JS objects? In JS JSON.parse, what are the parameters and processing details of these functions JSON.stringify?toJSON

Welcome to this "Journey to Dig Deep in JSON", the following will understand JSON from the following aspects:

  • The first is the understanding of "JSON is a lightweight data exchange format";
  • Then look at the difference between JSON and JS objects that are often confused;
  • Finally, let's look at the specific execution details of these JSON-related functions in JS.

I hope that the full text can help those who have a little knowledge of JSON like me before can explain clearly what JSON is, and can use JSON proficiently, without looking at the console to know what the output is after JS objects are serialized into JSON strings.

1. JSON is a format, based on text, better than lightweight for exchanging data

If you haven't been to the official introduction of JSON, you can go here . The first and second paragraphs of the official introduction have clearly stated what JSON is. I have refined what JSON is into the following aspects:

1. A data format

What is the format? It is to standardize how your data should be represented. For example, there is a person named "two hundred and six", with a height of "160cm" and a weight of "60kg". Now you want to pass this person's information to others or something else. You have many options:

  • 姓名“二百六”,身高“160cm”,体重“60kg”
  • name="二百六"&height="160cm"&weight="60kg"
  • <person><name>二百六</name><height>160</height><weight>60</weight></person>
  • {"name":"二百六","height":160,"weight":60}
  • ... ...

All the above options, the data passed is the same, but you can see that the form can be various, this is the data formatted in various ways, JSON is one of the representation methods.

2. Text-based data formats

JSON is a text-based data format, compared to binary-based data, so when JSON is passed, it passes a string that conforms to the JSON format (as to what the JSON format is, we will talk about it in the second part), we often call it "" JSON string".

3. Lightweight data format

Before JSON, there was a data format called xml, which is still widely used now, but JSON is more lightweight. If xmlyou need to use a lot of tags, like in the above example, you can clearly see xmlthat the tags themselves occupy a lot of space in the format data , and JSON is relatively lightweight, that is, the same data, the bandwidth occupied by the JSON format is smaller, which has obvious advantages in the case of a large amount of data request and transmission.

4. Widely used for data exchange

Lightweight is already an advantage for data exchange, but more importantly JSON is easy to read, write and machine parse, i.e. this JSON is both human and machine friendly, and is lightweight and language independent (because it is text-based), so JSON is widely used for data exchange.

Take the front-end JS for an ajax POST request as an example, and the back-end PHP to process the request as an example:

  1. The front-end constructs a JS object to wrap the data to be passed, then converts the JS object into a JSON string, and sends the request to the back-end;
  2. The backend PHP receives this JSON string, converts the JSON string to a PHP object, and then processes the request.

It can be seen that the same data has three different representations here, namely, the front-end JS object, the transmitted JSON string, and the back-end PHP object. The JS object and the PHP object are obviously not the same thing, but because everyone uses It is all JSON to transmit data. Everyone can understand this data format, and can easily convert the JSON data format into a data structure that they can understand. This is convenient for exchanging data in other language environments. It's all like that.

Second, the "gossip" between JSON and JS objects

Many times I heard the phrase "JSON is a subset of JS", and I always thought this sentence, every string that conforms to the JSON format can be parsed into JS, until I found out later a weird thing...

1. Why are two fundamentally different things so close?

JSON and JS objects are not the same thing at all, just like "zebra crossing" and "zebra", "zebra crossing" is presented and named based on the stripes on the "zebra", but zebras are living, and zebra crossings are non-living things.

Also, "JSON" is full name of "JavaScript Object Notation", so its format (syntax) is based on JS, but it is a format, and a JS object is an instance, a thing that exists in memory.

Just kidding, if JSON is based on PHP, it may be called PON, and the form may be like this ['propertyOne' => 'foo', 'propertyTwo' => 42,]. If so, then JSON may be close to PHP now.

In addition, JSON can be transmitted because it is in text format, but JS objects cannot be transmitted. In terms of syntax, JSON will be more strict, but JS objects are very loose.

So why are two different things so close, because JSON evolved from JS after all, and the syntax is similar.

2. What is the strictness of JSON format and JS object syntax?

First, let's compare the differences between the two in the form of "objects represented by key-value pairs". As for how JSON can be expressed, we will list them after the comparison.

Compare content JSON JS object
key name must be enclosed in double quotes It is allowed to not add, add single quotes, add double quotes
attribute value Can only be numeric (decimal), string (double quotes), boolean value and null, <br /> can also be an array or an object that conforms to JSON requirements, <br /> cannot be a function, NaN, Infinity, - Infinity and undefined love what
comma problem There cannot be a comma after the last attribute Can
Numerical value Leading 0 cannot be used, there must be a number after the decimal point no limit

It can be seen that JSON has a stricter format than JS objects, so most of the JS objects written do not conform to the JSON format.

The following code is quoted from here

var obj1 = {}; // 这只是 JS 对象

// 可把这个称做:JSON 格式的 JavaScript 对象 
var obj2 = {"width":100,"height":200,"name":"rose"};

// 可把这个称做:JSON 格式的字符串
var str1 = '{"width":100,"height":200,"name":"rose"}';

// 这个可叫 JSON 格式的数组,是 JSON 的稍复杂一点的形式
var arr = [
    {"width":100,"height":200,"name":"rose"},
    {"width":100,"height":200,"name":"rose"},
    {"width":100,"height":200,"name":"rose"},
];
        
// 这个可叫稍复杂一点的 JSON 格式的字符串     
var str2='['+
    '{"width":100,"height":200,"name":"rose"},'+
    '{"width":100,"height":200,"name":"rose"},'+
    '{"width":100,"height":200,"name":"rose"},'+
']';

Also, in addition to the usual "normal" JSON format, represented either as an object {...}or as an array [...], any single decimal value, double-quoted string, boolean, and null are valid JSON-compliant of.

Full JSON syntax reference here

3. An interesting point, JSON is not a subset of JS

First look at the following code, you can copy it to the console and execute it:

var code = '"\u2028\u2029"';
JSON.parse(code); // works fine
eval(code); // fails

These two characters \u2028and \u2029represent line separators and paragraph separators, respectively. JSON.parse can parse it normally, but it will report an error when js parsing.

3. What are the JSON functions in these JS?

In JS, we will mainly come into contact with two JSON-related functions, which are used for the conversion between JSON strings and JS data structures. One is called JSON.stringify, it is so smart that you write JS objects that do not conform to the JSON format. All can help you process strings that conform to JSON format, so you have to know what it does, lest it just be smart and let you debug for a long time; another is called JSON.parse, used to convert json strings to JS data structures, It is very strict, your JSON string cannot be parsed if it is not constructed correctly.

And they have more than one parameter, although only one parameter is passed in when we often use it.

Also, there's a toJSONfunction that we've seen less often, but it has an impact JSON.stringify.

1. Convert JS data structure to JSON string - JSON.stringify

The function signature of this function is this:

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

The following will expand the usage with 1~3 parameters, and finally some "smart" things it does during serialization, which should be paid special attention.

1.1 Basic usage - only one parameter

Everyone will use this, pass in a JS object or array in JSON format, and JSON.stringify({"name":"Good Man","age":18})return a string "{"name":"Good Man","age":18}".

It can be seen that the JS object we passed in is in JSON format, using double quotes, and there is no attribute value that JSON does not accept, then if it is like the example at the beginning, how to play? Don't worry, let's take a simple example to illustrate the meaning of several parameters of this function, and then talk about this problem.

1.2 The second parameter can be a function or an array

  • If the second parameter is a function, then every attribute during serialization will be transformed and processed by this function
  • If the second parameter is an array, then only properties contained in this array will be serialized into the final JSON string
  • If the second parameter is null, it is no different from empty, but if you don't want to set the second parameter, but just want to set the third parameter, you can set the second parameter to null

This second parameter is a function

var friend={
	"firstName": "Good",
	"lastName": "Man",
	"phone":"1234567",
	"age":18
};

var friendAfter=JSON.stringify(friend,function(key,value){
	if(key==="phone")
		return "(000)"+value;
	else if(typeof value === "number")
		return value + 10;
	else
		return value; //如果你把这个else分句删除,那么结果会是undefined
});

console.log(friendAfter);
//输出:{"firstName":"Good","lastName":"Man","phone":"(000)1234567","age":28}

If the second parameter is a function, then the function must return each item. This function accepts two parameters, a key name and an attribute value. The function must have a value for each original attribute value. Return of the new property value.

So the question is, what if the object form of the key-value pair is not passed in, but the array form of square brackets? , for example, the above friendbecomes like this: friend=["Jack","Rose"], then what are the key and value received by this attribute-by-attribute processing function? If it is in the form of an array, then the key is the index value, and the value is the array item. You can print out the key and value verification inside this function on the console. Remember to return the value inside the function, otherwise an error will occur.

The second parameter is an array

var friend={
	"firstName": "Good",
	"lastName": "Man",
	"phone":"1234567",
	"age":18
};

//注意下面的数组有一个值并不是上面对象的任何一个属性名
var friendAfter=JSON.stringify(friend,["firstName","address","phone"]);

console.log(friendAfter);
//{"firstName":"Good","phone":"1234567"}
//指定的“address”由于没有在原来的对象中找到而被忽略

If the second argument is an array, then only properties that appear in the array will be serialized into the result string, and properties that are not found in the provided array will not be included, and the array Properties that exist but do not exist in the source JS object will be ignored and no error will be reported.

1.3 The third parameter is used to beautify the output - not recommended

Specifies the whitespace character for indentation, which can take the following values:

  • is a number from 1-10, representing several blank characters
  • If it is a string, use the string instead of spaces, and take the first 10 characters of the string at most
  • Not providing this parameter is equivalent to setting it to null is equivalent to setting a number less than 1
var friend={
	"firstName": "Good",
	"lastName": "Man",
	"phone":{"home":"1234567","work":"7654321"}
};

//直接转化是这样的:
//{"firstName":"Good","lastName":"Man","phone":{"home":"1234567","work":"7654321"}}

var friendAfter=JSON.stringify(friend,null,4);
console.log(friendAfter);
/*
{
    "firstName": "Good",
    "lastName": "Man",
    "phone": {
        "home": "1234567",
        "work": "7654321"
    }
}
*/

var friendAfter=JSON.stringify(friend,null,"HAHAHAHA");
console.log(friendAfter);
/*
{
HAHAHAHA"firstName": "Good",
HAHAHAHA"lastName": "Man",
HAHAHAHA"phone": {
HAHAHAHAHAHAHAHA"home": "1234567",
HAHAHAHAHAHAHAHA"work": "7654321"
HAHAHAHA}
}
*/

var friendAfter=JSON.stringify(friend,null,"WhatAreYouDoingNow");
console.log(friendAfter);
/* 最多只取10个字符
{
WhatAreYou"firstName": "Good",
WhatAreYou"lastName": "Man",
WhatAreYou"phone": {
WhatAreYouWhatAreYou"home": "1234567",
WhatAreYouWhatAreYou"work": "7654321"
WhatAreYou}
}
*/

Just smile, don't use it like this, serialization is for transmission, and the transmission is as small as possible, adding inexplicable indents, difficult to parse (if it is a string), and weakening the feature of lightweight. .

1.4 Note the "little cleverness" of this function (important)

If there are other uncertain situations, then the best way is "Have a try", and it will be clear by experimenting on the console.

  • If the key name is not double quotes (including no quotes or single quotes), it will automatically become double quotes; if the string is single quotes, it will automatically become double quotes

  • The comma after the last attribute will be automatically removed

  • The properties of non-array objects are not guaranteed to appear in the serialized string in a specific order.
    This is easy to understand, that is, the order of properties of non-array objects in the final string is not guaranteed to be the same as the original.

  • The wrapper objects of boolean values, numbers, and strings will be automatically converted into the corresponding primitive values ​​during the serialization process, that
    is, what yours new String("bala")will become "bala", new Number(2017)will become2017

  • undefined, arbitrary functions ( in fact, there is a function that will do magical things, we will talk about it later ) and symbol values ​​(for symbols, see ES6's introduction to symbols)

    • Appears in property values ​​of non-array objects : ignored during serialization
    • When present in an array : converted to null
JSON.stringify({x: undefined, y: function(){return 1;}, z: Symbol("")});
//出现在非数组对象的属性值中被忽略:"{}"
JSON.stringify([undefined, Object, Symbol("")]);
//出现在数组对象的属性值中,变成null:"[null,null,null]"
  • NaN, Infinity, and -Infinity, both in arrays and non-array objects, are converted to null

  • All properties with symbol as property key will be completely ignored, even if they are forced to be included in the replacer parameter

  • Non-enumerable properties are ignored

2. Parse JSON string into JS data structure - JSON.parse

The function signature of this function is this:

JSON.parse(text[, reviver])

If the first parameter, the JSON string, is not a valid string, then this function will throw an error, so if you are writing a script that returns a JSON string in the backend, it is better to call the language's own JSON string related Serialization function, and if it is a serialized string that is implemented by splicing it yourself, then special attention should be paid to whether the serialized string is legal. Legal means that the JSON string fully conforms to the strict format required by JSON .

It is worth noting that there is an optional second parameter, this parameter must be a function, this function acts on the attribute has been parsed but has not returned before, the attribute is processed and then returned.

var friend={
	"firstName": "Good",
	"lastName": "Man",
	"phone":{"home":"1234567","work":["7654321","999000"]}
};

//我们先将其序列化
var friendAfter=JSON.stringify(friend);
//'{"firstName":"Good","lastName":"Man","phone":{"home":"1234567","work":["7654321","999000"]}}'

//再将其解析出来,在第二个参数的函数中打印出key和value
JSON.parse(friendAfter,function(k,v){
    console.log(k);
    console.log(v);
    console.log("----");
});
/*
firstName
Good
----
lastName
Man
----
home
1234567
----
0
7654321
----
1
999000
----
work
[]
----
phone
Object
----

Object
----
*/

Looking at these outputs carefully, you can find that this traversal is from the inside out. You may misunderstand the word inside out. The innermost layer is the two values ​​​​in the internal array, but the output starts from the first attribute. Yes, why is it from the inside out?

This inside-out refers to composite attributes . In layman's terms, when traversing, traverse from beginning to end. If it is a simple attribute value (number, string, Boolean value, and null), then the traversal is completed directly. , if the property value is in the form of an object or an array, then pause and traverse the sub-JSON first , and the principle of traversal is the same. After the traversal of the composite property is completed , then complete the traversal of the property and return.

Essentially, this is a depth-first traversal.

There are two things to note:

  • If the reviver returns undefined, the current property will be deleted from the object to which it belongs. If another value is returned, the returned value will become the new property value of the current property.
  • You can notice that the last set of output in the above example does not seem to have a key, but the key is actually an empty string, and the last object is the final parsed object, because at the top level, there are no real attributes.

3. The magic function that affects JSON.stringify - object.toJSON

If you implement a method on a JS object toJSON, when you call JSON.stringifyto serialize the JS object, the value returned by JSON.stringifythe method of the object will be toJSONused as a parameter to serialize.

var info={
    "msg":"I Love You",
    "toJSON":function(){
        var replaceMsg=new Object();
        replaceMsg["msg"]="Go Die";
        return replaceMsg;
    }
};

JSON.stringify(info);
//出si了,返回的是:'"{"msg":"Go Die"}"',说好的忽略函数呢

This function is like this.

In fact, the Datetype can be directly passed JSON.stringifyto the parameter, the reason is that the Datetype has a built-in toJSONmethod.

4. Summary and questions about compatibility

At this point, I finally sorted out JSON and JSON in JS, and traversed the details and points of attention. I know that JSON is a lightweight data exchange format derived from the JS language. , I also understand the difference between JSON and general JS data structures (especially objects), and go a step further and carefully discuss the three functions and details of JSON processing in JS.

Unfortunately, the three functions used above are not compatible with IE7 and browsers before IE7. The discussion of compatibility is for later. If you want to solve the compatibility directly on the application, you can apply the JSON official js, which can be solved.

If there are any mistakes, please leave a message to point out.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325482602&siteId=291194637