Поиск…


Вступление

JSON (JavaScript Object Notation) - это облегченный формат обмена данными. Человеку легко читать и писать и легко обрабатывать и генерировать машины. Важно понимать, что в JavaScript JSON является строкой, а не объектом.

Основной обзор можно найти на веб-сайте json.org, который также содержит ссылки на реализацию стандарта на многих языках программирования.

Синтаксис

  • JSON.parse (вход [, reviver])
  • JSON.stringify (значение [, replacer [, space]])

параметры

параметр подробности
JSON.parse Разбор строки JSON
input(string) Строка JSON обрабатывается.
reviver(function) Предписывает преобразование для входной строки JSON.
JSON.stringify Сериализовать сериализуемое значение
value(string) Значение для сериализации в соответствии со спецификацией JSON.
replacer(function или String[] или Number[]) Селективно включает определенные свойства объекта value .
space(String или Number ) Если задано number , тогда space пробелов будет вставлен в читаемость. Если string указана, строка (первые 10 символов) будет использоваться как пробелы.

замечания

Методы утилиты JSON были сначала стандартизованы в ECMAScript 5.1 §15.12 .

Формат был формально определен в приложении / json Media Type для JSON (RFC 4627, июль 2006 г.), который был позже обновлен в формате обмена данными JSON (RFC 7158, март 2013 г., ECMA-404, октябрь 2013 г. и RFC 7159, март 2014 г.).

Чтобы эти методы были доступны в старых браузерах, таких как Internet Explorer 8, используйте json2.js Douglas Crockford.

Разбор простой строки JSON

Метод JSON.parse() анализирует строку как JSON и возвращает примитив, массив или объект JavaScript:

const array = JSON.parse('[1, 2, "c", "d", {"e": false}]');
console.log(array); // logs: [1, 2, "c", "d", {e: false}]

Сериализация значения

Значение JavaScript может быть преобразовано в строку JSON с использованием функции JSON.stringify .

JSON.stringify(value[, replacer[, space]])
  1. value Значение для преобразования в строку JSON.
/* Boolean */  JSON.stringify(true)             // 'true'
/* Number  */  JSON.stringify(12)               // '12'
/* String  */  JSON.stringify('foo')            // '"foo"'
/* Object  */  JSON.stringify({})               // '{}'
               JSON.stringify({foo: 'baz'})     // '{"foo": "baz"}'
/* Array   */  JSON.stringify([1, true, 'foo']) // '[1, true, "foo"]'
/* Date    */  JSON.stringify(new Date())       // '"2016-08-06T17:25:23.588Z"'
/* Symbol  */  JSON.stringify({x:Symbol()})     // '{}'
  1. replacer Функция, которая изменяет поведение процесса строковой привязки или массив объектов String и Number, которые служат в качестве белого списка для фильтрации свойств объекта значения, который должен быть включен в строку JSON. Если это значение равно null или не указано, все свойства объекта включаются в результирующую строку JSON.
// replacer as a function
function replacer (key, value) {
    // Filtering out properties
    if (typeof value === "string") {
        return
    }    
    return value
}

var foo = { foundation: "Mozilla", model: "box", week: 45, transport: "car", month: 7 }
JSON.stringify(foo, replacer)
// -> '{"week": 45, "month": 7}'
// replacer as an array
JSON.stringify(foo, ['foundation', 'week', 'month'])
// -> '{"foundation": "Mozilla", "week": 45, "month": 7}'
// only the `foundation`, `week`, and `month` properties are kept
  1. space Для удобства чтения в качестве третьего параметра можно указать количество пробелов, используемых для отступов.
JSON.stringify({x: 1, y: 1}, null, 2)  // 2 space characters will be used for indentation
/* output:
    {
      'x': 1,
      'y': 1
    }
*/

В качестве альтернативы можно использовать строковое значение для использования для отступов. Например, передача '\t' приведет к тому, что символ табуляции будет использоваться для отступов.

JSON.stringify({x: 1, y: 1}, null, '\t')
/* output:
    {
        'x': 1,
        'y': 1
    }
*/

Сериализация с помощью функции замены

Функция replacer может использоваться для фильтрации или преобразования значений, которые сериализуются.

const userRecords = [
  {name: "Joe", points: 14.9, level: 31.5},
  {name: "Jane", points: 35.5, level: 74.4},
  {name: "Jacob", points: 18.5, level: 41.2},
  {name: "Jessie", points: 15.1, level: 28.1},
];

// Remove names and round numbers to integers to anonymize records before sharing
const anonymousReport = JSON.stringify(userRecords, (key, value) =>
  key === 'name'
    ? undefined
    : (typeof value === 'number' ? Math.floor(value) : value)
);

Это создает следующую строку:

'[{"points":14,"level":31},{"points":35,"level":74},{"points":18,"level":41},{"points":15,"level":28}]'

Разбор с функцией reviver

Функция reviver может использоваться для фильтрации или преобразования обрабатываемого значения.

5,1
var jsonString = '[{"name":"John","score":51},{"name":"Jack","score":17}]';

var data = JSON.parse(jsonString, function reviver(key, value) {
  return key === 'name' ? value.toUpperCase() : value;
});
6
const jsonString = '[{"name":"John","score":51},{"name":"Jack","score":17}]';

const data = JSON.parse(jsonString, (key, value) =>
  key === 'name' ? value.toUpperCase() : value
);

Это дает следующий результат:

[
  {
    'name': 'JOHN',
    'score': 51
  },
  {
    'name': 'JACK',
    'score': 17
  }
]

Это особенно полезно, когда необходимо отправить данные, которые должны быть сериализованы / закодированы при передаче с помощью JSON, но вы хотите получить доступ к десериализации / декодированию. В следующем примере дата была закодирована в соответствии с представлением ISO 8601. Мы используем функцию reviver для синтаксического анализа этого в Date JavaScript.

5,1
var jsonString = '{"date":"2016-01-04T23:00:00.000Z"}';

var data = JSON.parse(jsonString, function (key, value) {
  return (key === 'date') ? new Date(value) : value;
});
6
const jsonString = '{"date":"2016-01-04T23:00:00.000Z"}';

const data = JSON.parse(jsonString, (key, value) =>
  key === 'date' ? new Date(value) : value
);

Важно убедиться, что функция reviver возвращает полезное значение в конце каждой итерации. Если функция reviver возвращает undefined , никакое значение или выполнение не падает в конце функции, свойство удаляется из объекта. В противном случае свойство переопределяется как возвращаемое значение.

Сериализация и восстановление экземпляров классов

Вы можете использовать пользовательский метод toJSON и функцию toJSON для передачи экземпляров вашего собственного класса в JSON. Если у объекта есть метод toJSON , его результат будет сериализован вместо самого объекта.

6
function Car(color, speed) {
  this.color = color;
  this.speed = speed;
}

Car.prototype.toJSON = function() {
  return {
    $type: 'com.example.Car',
    color: this.color,
    speed: this.speed
  };
};

Car.fromJSON = function(data) {
  return new Car(data.color, data.speed);
};
6
class Car {
  constructor(color, speed) {
    this.color = color;
    this.speed = speed;
    this.id_ = Math.random();
  }

  toJSON() {
    return {
      $type: 'com.example.Car',
      color: this.color,
      speed: this.speed
    };
  }

  static fromJSON(data) {
    return new Car(data.color, data.speed);
  }
}
var userJson = JSON.stringify({
  name: "John",
  car: new Car('red', 'fast')
});

Это создает строку со следующим содержимым:

{"name":"John","car":{"$type":"com.example.Car","color":"red","speed":"fast"}}
var userObject = JSON.parse(userJson, function reviver(key, value) {
  return (value && value.$type === 'com.example.Car') ? Car.fromJSON(value) : value;
});

Это создает следующий объект:

{
  name: "John",
  car: Car {
    color: "red",
    speed: "fast",
    id_: 0.19349242527065402
  }
}

JSON по сравнению с литералами JavaScript

JSON означает «Обозначение объектов JavaScript», но это не JavaScript. Подумайте об этом , как только формат сериализации данных, случается, непосредственно используемых в качестве литерала JavaScript. Однако нецелесообразно напрямую запускать (т. eval() Через eval() ) JSON, который извлекается из внешнего источника. Функционально JSON не сильно отличается от XML или YAML - некоторые путаницы можно избежать, если JSON просто представляется как некоторый формат сериализации, который очень похож на JavaScript.

Хотя имя подразумевает только объекты, и хотя большинство случаев использования через какой-то API всегда бывают объектами и массивами, JSON - это не только объекты или массивы. Поддерживаются следующие примитивные типы:

  • String (например, "Hello World!" )
  • Номер (например, 42 )
  • Логическое (например, true )
  • Значение null

undefined не поддерживается в том смысле, что неопределенное свойство будет опущено из JSON при сериализации. Поэтому нет способа десериализовать JSON и получить свойство, значение которого undefined .

Строка "42" действительна JSON. JSON не всегда должен иметь внешний конверт "{...}" или "[...]" .

В то время как nome JSON также является действующим JavaScript, и некоторый JavaScript также действителен JSON, существуют некоторые тонкие различия между обоими языками, и ни один язык не является подмножеством другого.

Возьмем следующую строку JSON в качестве примера:

{"color": "blue"}

Это можно вставить непосредственно в JavaScript. Он будет синтаксически действительным и даст правильное значение:

const skin = {"color": "blue"};

Однако мы знаем, что «цвет» является допустимым именем идентификатора, и кавычки вокруг имени свойства могут быть опущены:

const skin = {color: "blue"};

Мы также знаем, что вместо двойных кавычек мы можем использовать одинарные кавычки:

const skin = {'color': 'blue'};

Но, если бы мы взяли оба эти литерала и относились к ним как к JSON, то ни один из них не будет синтаксически действительным JSON:

{color: "blue"}
{'color': 'blue'}

JSON строго требует, чтобы все имена свойств были двойными кавычками, а строковые значения также были двойными.

Для новичков JSON принято пытаться использовать фрагменты кода с литералами JavaScript как JSON и поцарапать их головы о синтаксических ошибках, которые они получают от анализатора JSON.

Появляется больше путаницы, когда неправильная терминология применяется в коде или в разговоре.

Общий анти-шаблон - это имя переменных, которые не имеют значения JSON как «json»:

fetch(url).then(function (response) {
  const json = JSON.parse(response.data); // Confusion ensues!

  // We're done with the notion of "JSON" at this point,
  // but the concept stuck with the variable name.
});

В приведенном выше примере response.data - это строка JSON, возвращаемая некоторым API. JSON останавливается в домене ответа HTTP. Переменная с неправильным словом «json» содержит только значение JavaScript (может быть объект, массив или даже простое число!)

Менее сложный способ написать выше:

fetch(url).then(function (response) {
  const value = JSON.parse(response.data);

  // We're done with the notion of "JSON" at this point.
  // You don't talk about JSON after parsing JSON.
});

Разработчики также склонны часто высказывать фразу «объект JSON». Это также приводит к путанице. Поскольку, как упоминалось выше, строка JSON не должна содержать объект в качестве значения. «Строка JSON» - лучший термин. Также как «строка XML» или «строка YAML». Вы получаете строку, вы разбираете ее, и вы получаете значение.

Циклические значения объекта

Не все объекты могут быть преобразованы в строку JSON. Когда объект имеет циклические самореференции, преобразование завершится неудачей.

Это типично для иерархических структур данных, где родительский и дочерний языки ссылаются друг на друга:

const world = {
  name: 'World',
  regions: []
};

world.regions.push({
  name: 'North America',
  parent: 'America'
});
console.log(JSON.stringify(world));
// {"name":"World","regions":[{"name":"North America","parent":"America"}]}

world.regions.push({
  name: 'Asia',
  parent: world
});

console.log(JSON.stringify(world));
// Uncaught TypeError: Converting circular structure to JSON

Как только процесс обнаруживает цикл, исключение возникает. Если бы не было обнаружения цикла, строка была бы бесконечно длинной.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow