Loading...

JSON форматы, toJSON ыкмасы

JSON форматы, toJSON ыкмасы

 

Келгиле, бизде татаал объект бар дейли жана биз аны тармак аркылуу жөнөтүү үчүн же жөн эле журналга чыгаруу үчүн сапка айландыргыбыз келет.

Албетте, мындай линия бардык маанилүү касиеттерин камтышы керек.

Биз трансформацияны төмөнкүдөй ишке ашыра алабыз:

@A@let user = {
  name: "John",
  age: 30,

  toString() {
    return `{name: "${this.name}", age: ${this.age}}`;
  }
};

alert(user); // {name: "John", age: 30}@A@

...Бирок иштеп чыгуу процессинде жаңы касиеттер кошулуп, эски касиеттер өзгөртүлүп, алынып салынат. Муну ар дайым жаңыртуу toStringкөйгөй жаратышы мүмкүн. Биз андагы касиеттерди кайталаганга аракет кылсак болот, бирок объект татаал болсо жана анын касиеттеринде уя салынган объекттер болсочы? Биз алардын трансформациясын да ишке ашырышыбыз керек болчу.

Бактыга жараша, мунун баарын чечүү үчүн код жазуунун кереги жок. Маселенин жөнөкөй чечими бар.

JSON.stringify

JSON (JavaScript Object Notation) баалуулуктарды жана объекттерди көрсөтүү үчүн жалпы формат болуп саналат. Анын сүрөттөлүшү RFC 4627 документтештирилген . Ал башында JavaScript үчүн түзүлгөн, бирок башка көптөгөн тилдерде да аны менен иштей ала турган китепканалар бар. Ошентип, кардар JavaScript колдонуп, сервер Ruby/PHP/Java же башка тилде жазылганда JSON маалымат алмашуу үчүн колдонууга оңой.

JavaScript ыкмаларды камсыз кылат:

  • JSON.stringifyобъекттерди JSONга айландыруу үчүн.
  • JSON.parseJSON кайра объектке айландыруу үчүн.

JSON.stringifyМисалы, бул жерде биз студенттин маалыматтары аркылуу конвертациялайбыз :

@A@let student = {
  name: 'John',
  age: 30,
  isAdmin: false,
  courses: ['html', 'css', 'js'],
  wife: null
};

let json = JSON.stringify(student);

alert(typeof json); // мы получили строку!

alert(json);
/* выведет объект в формате JSON:
{
  "name": "John",
  "age": 30,
  "isAdmin": false,
  "courses": ["html", "css", "js"],
  "wife": null
}
*/@A@

Метод JSON.stringify(student)объектти алып, аны сапка айлантат.

Натыйжада сап JSON форматталган же серияланганjson объект деп аталат . Биз аны тармак аркылуу жөнөтө алабыз же кадимки маалымат дүкөнүнө сала алабыз.

JSON объектисинин объектинин литералынан бир нече маанилүү айырмачылыктары бар экенин эске алыңыз:

  • Саптарда кош тырмакчалар колдонулат. JSONде бир да тырмакча же артка белги жок. Бул ушундай 'John'болуп калат "John".
  • Объекттин менчик аттары да кош тырмакчага алынат. Ал зарыл. Бул ушундай age:30болуп калат "age":30.

JSON.stringifyпримитивдерге да колдонсо болот.

JSON төмөнкү маалымат түрлөрүн колдойт:

  • Объекттер{ ... }
  • Массивдер[ ... ]
  • Примитивдер:
    • сызык,
    • сандар,
    • буль true/false,
    • null.

Мисалы:

@A@// число в JSON остаётся числом
alert( JSON.stringify(1) ) // 1

// строка в JSON по-прежнему остаётся строкой, но в двойных кавычках
alert( JSON.stringify('test') ) // "test"

alert( JSON.stringify(true) ); // true

alert( JSON.stringify([1, 2, 3]) ); // [1,2,3]@A@

JSON – бул маалыматтар үчүн тилден көз карандысыз спецификация, ошондуктан JSON.stringifyал JavaScript объекттеринин кээ бир спецификалык касиеттерин өткөрүп жиберет.

Тактап айтканда:

  • Properties-функциялар (ыкмалар).
  • Символикалык ачкычтар жана баалуулуктар.
  • камтыган касиеттери undefined.
@A@let user = {
  sayHi() { // будет пропущено
    alert("Hello");
  },
  [Symbol("id")]: 123, // также будет пропущено
  something: undefined // как и это - пропущено
};

alert( JSON.stringify(user) ); // {} (пустой объект)@A@

Адатта, бул нормалдуу көрүнүш. Эгерде бул биз каалагандай болбосо, анда биз бул процессти кантип ыңгайлаштырса болорун жакында көрөбүз.

Эң сонун нерсе, уя салынган объекттер колдоого алынат жана автоматтык түрдө айландырылат.

Мисалы:

@A@let meetup = {
  title: "Conference",
  room: {
    number: 23,
    participants: ["john", "ann"]
  }
};

alert( JSON.stringify(meetup) );
/* вся структура преобразована в строку:
{
  "title":"Conference",
  "room":{"number":23,"participants":["john","ann"]},
}
*/@A@

Маанилүү чектөө: тегерек шилтемелер болбошу керек.

Мисалы:

 
 
@A@let room = {
  number: 23
};

let meetup = {
  title: "Conference",
  participants: ["john", "ann"]
};

meetup.place = room;       // meetup ссылается на room
room.occupiedBy = meetup; // room ссылается на meetup

JSON.stringify(meetup); // Ошибка: Преобразование цикличной структуры в JSON@A@

Бул жерде конверсия тегерек шилтемеден улам ишке ашпай калды: room.occupiedByга шилтеме кылат meetupжана :meetup.placeroom

 

Жок кылуу жана өзгөртүү: алмаштыруучу

Толук синтаксис JSON.stringify:

@A@let json = JSON.stringify(value, [replacer, space])@A@

баалуулук

Коддоула турган маани.

алмаштыруучу

Коддоо үчүн касиеттердин массиви же дал келүүчү функция function(key, value).

космос

Форматтоо үчүн колдонулган кошумча орун (толтуру).

Көпчүлүк учурларда JSON.stringifyал биринчи аргумент менен гана колдонулат. Бирок биз алмаштыруу процессин ыңгайлаштырышыбыз керек болсо, мисалы, тегерек шилтемелерди чыпкалоо, анда экинчи аргумент колдонсо болот JSON.stringify.

Эгер биз ага касиеттердин массивдерин тапшырсак, ошол касиеттер гана коддолот.

Мисалы:

 
 
@A@let room = {
  number: 23
};

let meetup = {
  title: "Conference",
  participants: [{name: "John"}, {name: "Alice"}],
  place: room // meetup ссылается на room
};

room.occupiedBy = meetup; // room ссылается на meetup

alert( JSON.stringify(meetup, ['title', 'participants']) );
// {"title":"Conference","participants":[{},{}]}@A@

Бул жерде, балким, биз өтө катаал. Мүлк тизмеси объекттин бүт структурасына тиешелүү. Ошентип, ичинде participantsбош объекттер бар, анткени nameалар тизмеде жок.

room.occupiedByТегерек шилтемени пайда кылгандан башка бардык касиеттерди тизмектейли :

@A@let room = {
  number: 23
};

let meetup = {
  title: "Conference",
  participants: [{name: "John"}, {name: "Alice"}],
  place: room // meetup ссылается на room
};

room.occupiedBy = meetup; // room ссылается на meetup

alert( JSON.stringify(meetup, ['title', 'participants', 'place', 'name', 'number']) );
/*
{
  "title":"Conference",
  "participants":[{"name":"John"},{"name":"Alice"}],
  "place":{"number":23}
}
*/@A@

Азыр башкасынын баары occupiedByсериалдаштырылган. Бирок мүлктөрдүн тизмеси абдан узун.

Бактыга жараша, replacerмаани катары массивдин ордуна функцияны колдоно алабыз.

Функция ар бир жуп үчүн чакырылат (key, value)жана ал оригиналдын ордуна колдонула турган алмаштырылган маанини кайтарышы керек. Же undefinedмаанини өткөрүп жиберүү үчүн.

Биздин учурда, биз valueбашка бардык нерсе үчүн "кандай болсо, ошондой" кайтара алабыз occupiedBy. Көңүл бурбоо үчүн occupiedByтөмөнкү код кайтарат undefined:

@A@let room = {
  number: 23
};

let meetup = {
  title: "Conference",
  participants: [{name: "John"}, {name: "Alice"}],
  place: room // meetup ссылается на room
};

room.occupiedBy = meetup; // room ссылается на meetup

alert( JSON.stringify(meetup, function replacer(key, value) {
  alert(`${key}: ${value}`);
  return (key == 'occupiedBy') ? undefined : value;
}));

/* пары ключ:значение, которые приходят в replacer:
:             [object Object]
title:        Conference
participants: [object Object],[object Object]
0:            [object Object]
name:         John
1:            [object Object]
name:         Alice
place:        [object Object]
number:       23
occupiedBy: [object Object]
*/@A@

Функция replacerар бир ачкыч/маани жуптарын, анын ичинде уя салынган объектилерди жана массивдин элементтерин кабыл ала тургандыгын эске алыңыз. Жана ал рекурсивдүү түрдө колдонулат. thisИчиндеги маани replacer- учурдагы касиетти камтыган объект.

Биринчи кыйынчылык өзгөчө. Бул атайын "ороочу объект" өтүп жатат: {"": meetup}. Башкача айтканда, биринчи (key, value)жупта бош ачкыч бар, ал эми мааниси жалпысынан максаттуу. Ошондуктан жогорудагы мисалдагы биринчи сап болот ":[object Object]".

Идея мүмкүн болушунча көп варианттарды берүү replacer- ал керек болсо, бүт объектти талдоо жана алмаштыруу/өткөрүп жиберүү мүмкүнчүлүгүнө ээ.

Форматтоо: боштук

Үчүнчү аргумент - JSON.stringify(value, replacer, space)ыңгайлуу форматтоо үчүн колдонулган боштуктардын саны.

Мурда бардык JSON форматындагы объекттерде чегинүүлөр же кошумча боштуктар болгон эмес. Эгер объектти тармак аркылуу жөнөткүбүз келсе, бул жакшы. Аргумент spaceадам окуй турган чыгаруу үчүн гана колдонулат.

Төмөнкү space = 2JavaScript'ке уя салынган объекттерди объекттин ичиндеги 2 боштук менен чегинген бир нече сапта көрсөтүүнү айтат:

@A@let user = {
  name: "John",
  age: 25,
  roles: {
    isAdmin: false,
    isEditor: true
  }
};

alert(JSON.stringify(user, null, 2));
/* отступ в 2 пробела:
{
  "name": "John",
  "age": 25,
  "roles": {
    "isAdmin": false,
    "isEditor": true
  }
}
*/

/* для JSON.stringify(user, null, 4) результат содержит больше отступов:
{
    "name": "John",
    "age": 25,
    "roles": {
        "isAdmin": false,
        "isEditor": true
    }
}
*/@A@

Үчүнчү аргумент да сап болушу мүмкүн. Бул учурда, сап бир катар боштуктардын ордуна чегинүү үчүн колдонулат.

Параметр spaceжалаң гана журналды кесүү жана кооз чыгаруу үчүн колдонулат.

Ыңгайлаштырылган "toJSON"

Сапты конвертациялоодогудай эле toString, объект toJSONJSONга айландыруу ыкмасын бере алат. JSON.stringifyэгер ал бар болсо, аны автоматтык түрдө чакырат.

Мисалы:

@A@let room = {
  number: 23
};

let meetup = {
  title: "Conference",
  date: new Date(Date.UTC(2017, 0, 1)),
  room
};

alert( JSON.stringify(meetup) );
/*
  {
    "title":"Conference",
    "date":"2017-01-01T00:00:00.000Z",  // (1)
    "room": {"number":23}               // (2)
  }
*/@A@

Көрүнүп тургандай, date (1)ал жипке айланды. Себеби, типтеги бардык объектилерде мындай сапты кайтарып берүүчү Dateорнотулган ыкма бар .toJSON

toJSONЭми биздин объектибизге өзүбүздүн методубузду ишке ашыралы room (2):

@A@let room = {
  number: 23,
  toJSON() {
    return this.number;
  }
};

let meetup = {
  title: "Conference",
  room
};

alert( JSON.stringify(room) ); // 23

alert( JSON.stringify(meetup) );
/*
  {
    "title":"Conference",
    "room": 23
  }
*/@A@

Көрүнүп тургандай, ал түздөн-түз чакырылганда да , башка сериялануучу объектке уя салынганда toJSONда колдонулат .JSON.stringify(room)room

JSON.parse

JSON сапты коддон чыгаруу үчүн бизге JSON.parse деп аталган башка ыкма керек .

Синтаксис:

@A@let value = JSON.parse(str, [reviver]);@A@

көч

JSON объектке айландырылат.

жандандыруучу

Ар бир жуп үчүн чакырыла турган (ключ, значение) жана маанини конвертациялай турган кошумча функция.

Мисалы:

@A@// строковый массив
let numbers = "[0, 1, 2, 3]";

numbers = JSON.parse(numbers);

alert( numbers[1] ); // 1@A@

Же уя салынган объекттер үчүн:

@A@let user = '{ "name": "John", "age": 35, "isAdmin": false, "friends": [0,1,2,3] }';

user = JSON.parse(user);

alert( user.friends[1] ); // 1@A@

JSON зарыл болушунча татаал болушу мүмкүн, объекттер жана массивдер башка объекттерди жана массивдерди камтышы мүмкүн. Бирок алар бир JSON форматында болушу керек.

Бул жерде кол менен жазылган JSONдеги типтүү каталар (кээде мүчүлүштүктөрдү оңдоо үчүн жазышыңыз керек):

@A@let json = `{
  name: "John",                     // Ошибка: имя свойства без кавычек
  "surname": 'Smith',               // Ошибка: одинарные кавычки в значении (должны быть двойными)
  'isAdmin': false                  // Ошибка: одинарные кавычки в ключе (должны быть двойными)
  "birthday": new Date(2000, 2, 3), // Ошибка: не допускается конструктор "new", только значения.
  "friends": [0,1,2,3]                     // Здесь всё в порядке
}`;@A@

Ошондой эле, JSON комментарийлерди колдобойт. JSONге комментарий кошуу аны жараксыз кылат.

Тырмакчасыз ачкычтарды, комментарийлерди жана башкаларды колдогон дагы бир JSON5 форматы бар . Бирок бул тилдин спецификациясы эмес, өз алдынча китепкана.

Plain JSON ушунчалык катуу, анын иштеп чыгуучулары жалкоо болгондуктан эмес, коддоо жана окуу алгоритмин оңой, ишенимдүү жана өтө тез ишке ашырууга мүмкүндүк бергендиктен.

Reviver колдонуу

Элестеткиле, биз объектти meetupсерверден маалымат катары алдык.

Мына бири:

@A@// title: (meetup title), date: (meetup date)
let str = '{"title":"Conference","date":"2017-11-30T12:00:00.000Z"}';@A@

...А эми биз аны сериядан чыгарышыбыз керек , б.а. аны кайра JavaScript объектине айлантыңыз.

Келгиле, муну чалуу аркылуу кылалы JSON.parse:

 
 
@A@let str = '{"title":"Conference","date":"2017-11-30T12:00:00.000Z"}';

let meetup = JSON.parse(str);

alert( meetup.date.getDate() ); // Ошибка!@A@

Ой, ката!

Маани объект meetup.dateэмес, сап болуп саналат . DateАл бул сапты түрлөшү керек экенин кайдан JSON.parseбилсин Date?

JSON.parseКалыбына келтирүү функциясын экинчи аргумент катары өткөрүп берели , ал бардык маанилерди " dateболгондой " кайтарып берет, бирок Date:

 
 
@A@let str = '{"title":"Conference","date":"2017-11-30T12:00:00.000Z"}';

let meetup = JSON.parse(str, function(key, value) {
  if (key == 'date') return new Date(value);
  return value;
});

alert( meetup.date.getDate() ); // 30 - теперь работает!@A@

Айтмакчы, бул уя салынган объекттер үчүн да иштейт:

 
 
@A@let schedule = `{
  "meetups": [
    {"title":"Conference","date":"2017-11-30T12:00:00.000Z"},
    {"title":"Birthday","date":"2017-04-18T12:00:00.000Z"}
  ]
}`;

schedule = JSON.parse(schedule, function(key, value) {
  if (key == 'date') return new Date(value);
  return value;
});

alert( schedule.meetups[1].date.getDate() ); // 18 - отлично!@A@

Бардыгы

  • JSON – көпчүлүк программалоо тилдери үчүн өзүнүн көз карандысыз стандарты жана китепканалары бар маалымат форматы.
  • JSON жөнөкөй объекттерди, массивдерди, саптарды, сандарды, логикалык жана null.
  • JavaScript JSONге сериялаштыруу үчүн JSON.stringify ыкмаларын жана JSONден окуу үчүн JSON.parse ыкмаларын камсыз кылат.
  • Эки ыкма тең акылдуу окуу/жазуу айландыруу функцияларын колдойт.
  • Эгерде объекттин методу бар болсо toJSON, анда ал аркылуу деп аталат JSON.stringify.

Tasks

маанилүүлүгү: 5

JSONга айландырыңыз user, андан кийин ошол JSONди башка өзгөрмөгө окуңуз.

@A@let user = {
  name: "Василий Иванович",
  age: 35
};@A@
чечим
маанилүүлүгү: 5

Жөнөкөй учурларда тегерек шилтемелер, биз алардын аты менен катарлаштырылышына себеп болгон касиетти жокко чыгара алабыз.

Бирок кээде атын колдоно албайбыз, анткени уя салынган объекттерде бул ат менен башка касиеттер болушу мүмкүн. Ошондуктан, сиз баалуулугу боюнча мүлктү текшере аласыз.

replacerТөмөнкүгө шилтеме берген касиеттерди жок кыла турган JSON трансформация функциясын жазыңыз meetup:

 
 
@A@let room = {
  number: 23
};

let meetup = {
  title: "Совещание",
  occupiedBy: [{name: "Иванов"}, {name: "Петров"}],
  place: room
};

// цикличные ссылки
room.occupiedBy = meetup;
meetup.self = meetup;

alert( JSON.stringify(meetup, function replacer(key, value) {
  /* ваш код */
}));

/* в результате должно быть:
{
  "title":"Совещание",
  "occupiedBy":[{"name":"Иванов"},{"name":"Петров"}],
  "place":{"number":23}
}
*/@A@