Поиск…
Вступление
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]])
-
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()}) // '{}'
-
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
-
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 может использоваться для фильтрации или преобразования обрабатываемого значения.
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;
});
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.
var jsonString = '{"date":"2016-01-04T23:00:00.000Z"}';
var data = JSON.parse(jsonString, function (key, value) {
return (key === 'date') ? new Date(value) : value;
});
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
, его результат будет сериализован вместо самого объекта.
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);
};
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
Как только процесс обнаруживает цикл, исключение возникает. Если бы не было обнаружения цикла, строка была бы бесконечно длинной.