логотип PurpleSchool
Иконка входа
Вход
логотип PurpleSchool

JSON: методы, ограничения, примеры использования.

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

Синтаксис JSON и примеры использования

JSON (JavaScript Object Notation) очень похож на буквенный синтаксис объекта JavaScript с тем лишь отличием, что имена свойств всегда заключены в двойные кавычки, и не используются другие виды кавычек (одинарные, обратные). Кроме того данные в формате JSON нельзя сразу использовать в JavaScript. Для работы с ними у глобального объекта JSON существует два метода: JSON.stringify(), который при базовом использовании принимает данные с типом Object, Array, Number, String, Boolean и Null, после чего преобразует их в JSON строку и JSON.parse(), который преобразует данные из JSON.

const myArr = [{ first: 1 }, { second: 2 }];
const myObj = {
  myArr: myArr,
  myNum: 1,
  myStr: "Hello!",
  myBoolean: false,
};
const myJSON = JSON.stringify(myObj);
//{"myArr":[{"first":1},{"second":2}],"myNum":1,"myStr":"Hello!","myBoolean":false}
console.log(typeof myJSON); //string
const parsedObj = JSON.parse(myJSON);
//получаем исходный объект со всеми вложениями
console.log(typeof parsedObj);//object

1 JSON.png

Перевод данных в формат JSON и обратно используется не только для передачи данных по сети, но и для клонирования ссылочных типов данных. В нашем примере свойство myArr объекта parsedObj не будет ссылаться на объявленный в первой строке массив, а создаст его независимую копию.

Ограничения формата JSON и как их обойти

При описании метода JSON.stringify() я не просто так перечислил поддерживаемые типы данных. Дело в том, что JSON не умеет работать с типами Date, BigInt, Map и остальными, не попавшими в описаный список. Что бы преобразовать такие данные в JSON строку необходимо привести их к поддерживаемому типу. Сделать это можно прямо внутри метода, передав в него необязательным параметром функцию, которая принимает все пары ключ-значение и преобразует их по ходу работы метода.

const myObj = {
  bigInt: 123n,
  date: new Date("2023-08-27"),
};
console.log(JSON.stringify(myObj));//выдаст ошибку
//TypeError: Do not know how to serialize a BigInt

const replacer = (key, value) => {
  if (typeof value === "bigint") {
    return Number(value);
  }//проверяем тип значения 
  if (key === "date") {
    return value.toString();
  }//или ключ
  return value;//остальные значения просто возвращаем
};
const replacedObj = JSON.stringify(myObj, replacer);
//{"bigInt":123,"date":"2023-08-27T00:00:00.000Z"}

2 bigint.png

Кроме того JSON.stringify() не может работать с циклическими зависимостями. Что бы исключить из сериализации значения с такими зависимостями или если вам нужно преобразовать в JSON формат только часть объекта, можно вместо функции передать вторым параметром массив ключей и в результате метод вернет строку, содержащую только пары ключ-значение с этими ключами.

const person = { name: "John", age: "22" };
const company = { name: "Company", employers: [person] }; //company ссылается на person
person.company = company; //person ссылается на company

console.log(JSON.stringify(person));
//TypeError: Converting circular structure to JSON
const safetyProperties = Object.keys(person).filter(
  (elem) => elem !== "company"
); //создаем массив "безопасных" ключей
console.log(JSON.stringify(person, safetyProperties)); //{"name":"John","age":"22"}

3 circular.png

Дополнительные возможности JSON.

Метод parse() глобального объекта JSON тоже принимает дополнительным параметром функцию, которая по аналогии с JSON.stringify() обработает каждую пару ключ-значение при парсинге строки.

const JSONdata = JSON.stringify({ name: "john", age: 22 });
const capitalizeName = (key, value) => {
  if (key === "name") {
    capitalizedName = value.replace(value[0], value[0].toUpperCase());
    return capitalizedName;
  } //если ключ - name возвращаем имя с заглавной буквой в начале
  return value; //остальные значения просто возвращаем как есть
};
console.log(JSON.parse(JSONdata, capitalizeName)); //{ name: 'John', age: 22 }
//заменить функцию на массив ключей, как в JSON.stringify не получится
console.log(JSON.parse(JSONdata, ["name"])); //{ name: 'john', age: 22 }

4 parse.png

Кроме функции обработки пар ключ-значение, метод JSON.stringify() может принимать еще одним параметром вид отступов для более удобного при чтении форматирования получаемой строки. Важно помнить, что это третий параметр метода и если функция или массив не переданы вторым параметром - нужно указать вместо них null.

const myObj = { name: "John", age: 22 };
console.log(JSON.stringify(myObj, null, 4));
// {
//     "name": "John",
//     "age": 22
// }
console.log(JSON.stringify(myObj, null, 10));
// {
//           "name": "John",
//           "age": 22
// }
//если не передавать null или второй параметр
//форматирование останется стандартным
console.log(JSON.stringify(myObj, 10)); 
//{"name":"John","age":22}

5 space.png

Мы уже знаем что при вызове JSON.stringify() можно указать массив ключей или функцию, которая обработает все пары ключ-значение, но мы так же можем изменить поведение этого метода при описании объекта, который будет в него передаваться. Для этого нужно добавить такому объекту свойство toJSON и описать в нем функцию, возвращающую нужное нам значение. Таким образом можно “скрыть” для JSON.stringify() приватные данные или вовсе передавать значения полностью отличные от содержимого объекта.

const user = {
  name: "John",
  age: 22,
  password: "password",
  toJSON() {
    return { name: this.name, age: this.age };
  },//перечисляем свойства которые хотим передавать
};
console.log(JSON.stringify(user, null, 2));
// {
//     "name": "John",
//     "age": 22
//   }

6 toJSON.png

Заключение

Работа с данными формата JSON и методами одноименного глобального объекта в JavaScript давно стала неотъемлемой частью разработки веб приложений поэтому навыки взаимодействия с ними необходимы каждому разработчику.

Комментарии

0
изображение курса

Основы разработки

Антон Ларичев
иконка звёздочки рейтинга5.0
бесплатноПодробнее
Основы разработки
Бесплатно