Келгиле, бизде татаал объект бар дейли жана биз аны тармак аркылуу жөнөтүү үчүн же жөн эле журналга чыгаруу үчүн сапка айландыргыбыз келет.
Албетте, мындай линия бардык маанилүү касиеттерин камтышы керек.
Биз трансформацияны төмөнкүдөй ишке ашыра алабыз:
@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.parse
JSON кайра объектке айландыруу үчүн.
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.place
room
Жок кылуу жана өзгөртүү: алмаштыруучу
Толук синтаксис 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 = 2
JavaScript'ке уя салынган объекттерди объекттин ичиндеги 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
, объект toJSON
JSONга айландыруу ыкмасын бере алат. 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
JSONга айландырыңыз user
, андан кийин ошол JSONди башка өзгөрмөгө окуңуз.
@A@let user = {
name: "Василий Иванович",
age: 35
};@A@
Жөнөкөй учурларда тегерек шилтемелер, биз алардын аты менен катарлаштырылышына себеп болгон касиетти жокко чыгара алабыз.
Бирок кээде атын колдоно албайбыз, анткени уя салынган объекттерде бул ат менен башка касиеттер болушу мүмкүн. Ошондуктан, сиз баалуулугу боюнча мүлктү текшере аласыз.
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@