JSON is everywhere in the programming world.

  • So what is JSON?
  • What does it have to do with our JavaScript?
  • How do we deal with JSON data in JavaScript?

A, JSON

JSON (JavaScript Object Natation) is a lightweight data exchange format. Because it is easy to read, write, and machine parsed and generated, it is smaller, faster, and easier to parse than XML, making it an ideal data exchange language. A text format that is completely independent of language.

JSON has two structures:

  • Collection of name/value pairs: In different languages, it is understood as an object, record, struct, dictionary, hash table, keyed list, or associative array.
  • An ordered list of values: In most languages, this is understood as an array.

For example, use the following JSON data to describe a person’s information:

{
  "name": "Frankie"."age": 20."skills": ["Java"."JavaScript"."TypeScript"]}Copy the code

Note that JavaScript is not JSON, and JSON is not JavaScript. However, JSON and JavaScript have a long history. JSON data format evolved from JavaScript objects. (As can be seen from the name)

Second, JSON and JavaScript differences

JSON is a data format, or a specification. JSON is used for cross-platform data exchange, independent of language and platform. A JavaScript object, on the other hand, is an instance that exists in memory. JavaScript objects cannot be transferred until they are serialized as JSON strings.

JavaScript type Differences in JSON
Objects and Arrays Attribute names must be double-quoted strings; There cannot be a comma after the last attribute
The numerical Disallow leading zeros (JSON.stringify()Method automatically ignores leading zeros while theJSON.parse()Method will throw a SyntaxError); If there is a decimal point, it is followed by at least one digit.
string Only a limited number of characters can be escaped; Disallow certain control characters; Unicode line delimiters (U+2028) and segment delimiters (U+2029Be allowed to; Strings must be enclosed in double quotes. Please refer to the example below to seeJSON.parse()It parses normally, but is thrown when parsed as JavaScriptSyntaxErrorError:
Parse (code) // Normal eval(code) // errorCopy the code

In JavaScript, we cannot call the following objects JSON, such as:

// This is just a JS object
var people = {}

// This has nothing to do with JSON, just JS objects
var people = { name: 'Frankie'.age: 20 }

// This has nothing to do with JSON, just JS objects
var people = { 'name': 'Frankie'.'age': 20 }

// We can call this JS object in JSON format
var people = { "name": "Frankie"."age": 20 }

// We can call this a JSON string
var people = '{"name":"Frankie","age":20}'

// A slightly more complex array in JSON format
var peopleArr = [
  { "name": "Frankie"."age": 20 },
  { "name": "Mandy"."age": 18}]// A slightly complex jSON-formatted string
var peopleStr = '[{"name":"Frankie","age":20},{"name":"Mandy","age":18}]'
Copy the code

Although JSON is similar to the strict literal representation of JavaScript objects, it is not correct to interpret JavaScript object attributes in double quotes as JSON; it simply conforms to the syntax of JSON. JSON and JavaScript objects are essentially two different things, like “zebra” and “zebra crossing.”

In JavaScript, JSON objects contain two methods, json.parse () for parsing and json.stringify () for transforming. Aside from these two methods, the JSON object itself has no other function and cannot be called or invoked as a constructor.

Third, JSON. Stringify ()

Converts a JavaScript object or value to a JSON string.

JSON.stringify(value, replacer, space)

  • The parameter value is the value to be serialized as a JSON string.

  • Parameter replacer (optional), which, if it is a function, transforms and processes each property of the serialized value during serialization; If the parameter is an array, only the property names contained in the array will be serialized into the final JSON string; If this parameter is not provided (or the value is null), all attributes of the object are serialized.

const people = {
  name: 'Frankie'.age: 20
}

const peopleStr1 = JSON.stringify(people, ['name'])
const peopleStr2 = JSON.stringify(people, (key, value) = > {
  if (typeof value === 'string') {
    return undefined
  }
  return value
})

console.log(peopleStr1) // '{"name":"Frankie"}'
console.log(peopleStr2) // '{"age":20}'
Copy the code
  • parameterspace(Optional), specifies a blank string for indentation, which is used to beautify the output (pretty-print). If the parameter isdigital, which indicates how many Spaces there are. If the value is greater than 10, the output space is 10, and if the value is less than 1, there is no space. If the parameter isstring, the string will be used as a space. If the parameter is not provided (or has a value ofnull), there will be no Spaces. Note that if a non-empty string is used as a parameter value, it cannot beJSON.parse()It parses, it throwsSyntaxErrorError.

In general, the parameters replacer and space are rarely used.

See the sample:

const symbol = Symbol(a)const func = () = >{}const people = {
  name: 'Frankie'.age: 20.birthday: new Date(),
  sex: undefined.home: null.say: func,
  [symbol]: 'This is Symbol'.skills: [' '.undefined.'JavaScript'.undefined, symbol, func],
  course: {
    name: 'English'.score: 90
  },
  prop1: NaN.prop2: Infinity.prop3: new Boolean(true) // or new String('abc') or new Number(10)
}

const replacer = (key, value) = > {
  // I'm doing nothing here, just like ignoring the replacer argument.

  // Return undefined if it is not serialized.
  // if (typeof value === 'string') return undefined
  
  // You can also use this function to see the order in which serialization is executed.

  // console.log('key: ', key)
  // console.log('value: ', value)
  return value
}

// Serialize
const peopleStr = JSON.stringify(people, replacer)

// '{" name ":" Frankie, "" age" : 20, "birthday" : "the 2021-01-17 T10:24:39. 333 z", "home", null, "skills" : [" ", null, null, "JavaScript", null, n ull,null],"course":{"name":"English","score":90},"prop1":null,"prop2":null,"prop3":true}'
console.log(peopleStr) 

console.log(JSON.stringify(function(){})) // undefined
console.log(JSON.stringify(undefined)) // undefined
Copy the code
Combined with the above examples, it has the following characteristics:
  • Properties of non-array objects are not guaranteed to appear in a serialized string in a particular order. (The example may not show it)
  • Booleans, numbers, and string wrapper objects are automatically converted to their original values during serialization. (e.g.,prop3)
  • undefined, any function andsymbolValue, there are two different cases in the serialization process. If appear in theProperty value of a non-array object, will be ignored; If appear in theAn array ofIs converted tonull.
  • The function,undefinedReturns when converted separatelyundefined.
  • All properties with symbol as the property key are completely ignored, even thoughreplacerThey are mandatory in the parameter.
  • The Date Date calls its built-intoJSON()Method to convert it to a string (same asDate.toISOString()), so it is treated as a string.
  • NaNInfinityThe value of the format andnullWill be regarded asnull.
  • Other types of objects, includingMap,Set,WeakMap,WeakSetOnly enumerable attributes are serialized.
  • Convert value if containstoJSON()Method that defines what values will be serialized.
  • Executing this method on objects that contain circular references (objects that refer to each other in an infinite loop) throws an error.
To illustrate the last two points:
  • If the object itself is implementedtoJSON()Method, then callJSON.stringify()Method,JSON.stringify()It’s going to take this objecttoJSON()The return value of the method is serialized as an argument.
const people = {
  name: 'Frankie'.age: 20.toJSON: () = > {
    return { name: 'Mandy'}}}console.log(JSON.stringify(people))
/ / the result is {" name ":" Mandy "}, rather than {" name ":" Frankie, "" age" : 20}
// It is important to note that if the object's toJSON attribute value is not a function, the object is still serialized as a parameter.


// The Date object itself has a built-in toJSON() method, so the result is:
/ / ": the 2021-01-17 T09 40:08. 302 z"
console.log(JSON.stringify(new Date()))


// What if I changed the toJSON method on the Date prototype?
Date.prototype.toJSON = function () { return 'Rewritten' }
console.log(JSON.stringify(new Date())) // "rewritten"
Copy the code
  • Executing this method on objects that contain circular references (objects that refer to each other in an infinite loop) throws an error.
const foo = {}
const bar = {
  b: foo
}
foo.a = bar
console.log(foo)

// If foo is serialized at this point, an error is thrown.
JSON.stringify(foo) // Uncaught TypeError: Converting circular structure to JSON
Copy the code

Foo and bar will reference each other indefinitely. If foo is serialized, Uncaught TypeError will be raised: Converting circular structure to JSON.

To see other people’s solutions to this problem, see jSON-js here. To do this, import the cycli.js script and then json.stringify (json.decycle (foo)).

JSON. Stringify () conclusion:
  1. If the serialized object existstoJSON()Method, what’s really being serialized istoJSON()Method return value.
  2. If providedreplacerParameter to apply the function filter. The value of the function filter passed in is the value returned in step 1.
  3. Serialize each value returned in step 2.
  4. If providedspaceParameter to perform the corresponding formatting operation.

Four, JSON. The parse ()

The json.parse () method parses JSON strings to construct JavaScript values or objects described by the strings. Provides optional reviver functions to perform transformations (operations) on the resulting object before returning.

JSON.parse(text, reviver)

  • The text argument, a string to be parsed into a JavaScript value.

  • Parameter Reviver (optional) converter that, if passed, can be used to modify the original value generated by parsing before the parse function returns.

    If the reviver function is specified, the parsed JavaScript value (parsed value) will undergo a transformation before it is finally returned (return value). To be more specific, The reviver function will be called respectively in a certain order (starting from the innermost level of the attribute, moving up to the top level, that is, the attribute itself). During the call, the object to which the current attribute belongs will be used as this value. The current attribute name and attribute value are passed into the Reviver as the first and second parameters, respectively. If reviver returns undefined, the current attribute will be removed from the owning object. If other values are returned, the returned value will become the new attribute value of the current attribute.

    When traversing to the top-level value (the parsed value), the arguments passed to the reviver function will be an empty string “” (because there are no real attributes at this point) and the current parsed value (which may have been modified). The current this value will be {“”: }, a special case to be aware of when writing reviver functions. (This function is iterated in the following order: start at the innermost layer and work through the hierarchy.)

// JSON string
const peopleStr = '{" name ":" Frankie, "" age" : 20, "birthday" : "the 2021-01-17 T10:24:39. 333 z", "home", null, "skills" : [" ", null, null, "JavaScript", null, n ull,null],"course":{"name":"English","score":90},"prop1":null,"prop2":null,"prop3":true}'

// If you want to output this object, you cannot use the arrow function
const reviver = (key, value) = > {
  // You can use this function to see the order in which serialization is executed.
  // console.log('key: ', key)
  // console.log('value: ', value)

  // If an attribute is deleted, return undefined.
  // if (typeof value === 'string') return undefined

  // If it reaches the top level, the attribute value is returned directly
  if (key === ' ') return value

  // A numeric type that doubles the value of the property
  if (typeof value === 'number') return value * 2

  // The rest is unparsed
  return value
}

const parseObj = JSON.parse(peopleStr, reviver)

console.log(parseObj)
Copy the code

The analytical results are as follows:

{
  "age": 40."birthday": "The 2021-02-14 T06:02:18. 491 z"."course": { "name": "English"."score": 180 },
  "home": null."name": "Frankie"."prop1": null."prop2": null."prop3": true."skills": ["".null.null."JavaScript".null.null.null]}Copy the code

Five, the reference

  • JSON MDN
  • Introducing JSON
  • ECMA-404 The JSON Data Interchange Standard