Diyelim ki karmak bir yap var, bunu karakter dizisine evirip a zerinden loglanmas iin baka bir yere iletilmek isteniyor.
Doal olarak, bu karakter dizisi tm nemli zellikleri iermeli
Bu evirim u ekilde yaplabilir:
let kullanici = {
adi: "Ahmet",
yasi: 30,
toString() {
return `{adi: "${this.adi}", yasi: ${this.yasi}}`;
}
};
alert(kullanici); // {adi: "Ahmet", yasi: 30}
Fakat gelitirme esnasnda yeni zellikler eklendi ve ncekiler ya silindi ya da isim deitirdi. Byle bir durumda toString metoduyla her zaman deiiklik yapmak olduka zordur. zellikleri dngye sokup buradan deerler alnabilir. Bu durumda da i ie objelere ne olacak? Bunlarnda evirimlerini yapmak gerekir. Ayrca a zerinden objeyi gndermeye altnzda ayrca bu objenin alan yer tarafndan nasl okunacana dair bilgi gndermek zorundasnz.
Neyse ki bunlarn hibiri iin kod yazmaya gerek yok. Bu problem bizim iin zlm durumda.
JSON.stringify
JSON (JavaScript Object Notation) genelde objelerin deerlerini ifade eder.RFC 4627 standardnda tanm yaplmtr. ncelikle JavaScript dnlerek yaplm olsa da birok dil de kendine has ktphanelerle JSON destei vermektedir. Bylece client JavaScript kullanrken server Ruby/PHP/Java/Her neyse kullansa bile JSON kullanmnda bir sorun oluturmaz.
JavaScript aadaki metodlar destekler:
JSON.stringifyobjeyi JSONa evirir.JSON.parseJSONdan objeye evirmeye yarar.
rnein, aada JSON.stringify metodu grenci objesi iin kullanlmtr:
let ogrenci = {
adi: 'Ahmet',
yasi: 30,
adminMi: false,
dersler: ['html', 'css', 'js'],
esi: null
};
let json = JSON.stringify(ogrenci);
alert(typeof json); // string dnecektir.!
alert(json);
/* JSON'a evirilmi obje:
{
"adi": 'Ahmet',
"yasi": 30,
"adminMi": false,
"dersler": ['html', 'css', 'js'],
"esi": null
}
*/
JSON.stringify(ogrenci) metodu objeyi alr ve bunu karaktere evirir, buna Json-kodlanm , seri hale getirilmi veya karakter haline getirilmi denir. Bunu a zerinden kar tarafa gndermek veya basit bir ekilde kaydetmek mmkndr.
JSON kodlanm objenin normal obje ile arasnda birka tane nemli farkllk vardr:
- Karakterler ift trnak kullanr. JSONda tek trnak veya ters trnak kullanlmaz. Bundan dolay
'Ahmet'"Ahmet"olur. - Obje zelliklerinin isimleri de ift trnak iinde alnr. Bu da zorunludur. Bundan dolay
yas:30,"yas":30olur.
JSON.stringify ilkel tiplere de uygulanabilir.
Desteklenen JSON tipleri:
- Objeler
{ ... } - Diziler
[ ... ] - lkel Tipler:
- karakterler,
- saylar,
- boolean deerler
true/false, null.
rnein:
// normal bir say JSON iin de normal bir saydr.
alert( JSON.stringify(1) ) // 1
// karakterler de JSON iinde karakterdir fakat ift trnak iinde gsterilir.
alert( JSON.stringify('test') ) // "test"
alert( JSON.stringify(true) ); // true
alert( JSON.stringify([1, 2, 3]) ); // [1,2,3]
JSON sadece veriyi tanmlayan diller aras bir artname bulunmaktadr. Bundan dolay JavaScripte zel obje zelliklerikleri JSON.stringify tarafndan pas geilir.
Yani:
- Fonksiyon zellikleri ( metodlar ).
- Sembolik zellikler.
undefinedsaklayan zellikler.
let kullanici = {
merhaba() { // ihmal edilir
alert("Merhaba");
},
[Symbol("id")]: 123, // ihmal edilir
baska: undefined // ihmal edilir
};
alert( JSON.stringify(kullanici) ); // {} (bo obje)
Bu zellik kabul edilebilir. Eer istediiniz bu deilse, bu ilemi nasl zelletirebilirsiniz bunu greceksiniz.
Harika olan ise i ie objeler otomatik olarak evrilir.
rnein:
let tanisma = {
baslik: "Konferans",
oda: {
sayi: 123,
katilimcilar: ["ahmet", "mehmet"]
}
};
alert( JSON.stringify(tanisma) );
/* tm yap karakter ekline evrildi:
{
"tanisma":"baslik",
"oda":{"sayi":23,"katilimcilar":["ahmet","mehmet"]},
}
*/
nemli bir snrlama: Dairesel referans olmamaldr.
rnein:
let oda = {
sayi: 23
};
let tanisma = {
baslik: "Konferans",
katilimcilar: ["ahmet", "mehmet"]
};
tanisma.yeri = oda; // tanisma odaya referans veriyor.
oda.dolduruldu = tanisma; // oda tanismaya referans veriyor
JSON.stringify(tanisma); // Hata: Dairesel yap JSON'a evrilememitir.
eviri yaplrken hata olmasnn nedeni: oda.dolduruldu tanismaya referans olurken, tanisma.yeri odaya referans verir.
Hari tutmak ve dntrmek: yer deitirici ( replacer )
JSON.stringfyn tam yazm:
let json = JSON.stringify(deger[, degistirici, bosluk])
- deger
- Kodlanacak metin.
- degistirici
- Mapleme (haritalama) fonksiyonu (
function(key,value)) veya kodlanacak zelliklerin dizisi. - boluk
- Formatlanmak iin kullanlacak boluk.
ou zaman JSON.stringifyn sadece ilk argman kullanlr. Fakat daha derinlemesine bir deitirici ilemi yapmak istiyorsanz. rnein dairesel referans filtrelemek gibi, JSON.stringifyn dier argmanlarn da kullanabilirsiniz.
Eer nc parametreyi de gnderirseniz, sadece gnderdiiniz zellikler kodlanacaktr.
rnein:
let oda = {
sayi: 23
};
let tanisma = {
baslik: "Konferans",
katilimcilar: [{adi: "Ahmet"}, {adi: "Mehmet"}],
yer: oda // tanma oday referans gsteriyor.
};
oda.dolduruldu = tanisma; // oda tanmay referans gsteriyor.
alert( JSON.stringify(tanisma, ['baslik', 'katilimcilar']) );
// {"baslik":"Konferans","katilimcilar":[{},{}]}
Burada ok sk kullandk. zellik listesi tm yap iin kullanld. Bundan dolay katlmclar bo dndr, adi alan da istenseydi bu durumda deer gelecekti.
Dairesel referansa neden olabilecek oda.dolduruldu hari hepsini iermek isterseniz:
let oda = {
sayi: 23
};
let tanisma = {
baslik: "Konferans",
katilimcilar: [{adi: "Ahmet"}, {adi: "Mehmet"}],
yer: oda // tanma oday referans gsteriyor.
};
oda.dolduruldu = tanisma; // oda tanmay referans gsteriyor.
alert( JSON.stringify(tanisma, ['baslik', 'katilimcilar', 'yer', 'adi', 'sayi']) );
/*
{
"baslik":"Konferans",
"katilimcilar":[{"adi":"Ahmet"},{"adi":"Mehmet"}],
"yer":{"sayi":23}
}
*/
imdi ise dolduruldu hari her yer seri haline getirildi. Fakat zelliklerin listesi olduka byk oldu.
Neyse ki degistirici yerine fonksiyon kullanlabilir.
Bu fonksiyon her (anahtar, deger) ikilisi iin arlabilir ve deitirilmi deeri evirir, bu da orijinalinin yerine geer.
Daha nce yaptmz rnekte dolduruldu zellii hari dier zelliklerin degerin olduu gibi kullanlabilir. dolduruldu zelliini pas gemek iin aadaki kod undefined dndrr.
let oda = {
sayi: 23
};
let tanisma = {
baslik: "Konferans",
katilimcilar: [{adi: "Ahmet"}, {adi: "Mehmet"}],
yer: oda // tanma oday referans gsteriyor.
};
oda.dolduruldu = tanisma; // oda tanmay referans gsteriyor
alert( JSON.stringify(tanisma, function degistirici(anahtar, deger) {
alert(`${anahtar}: ${deger}`); // degistiriciye gelen
return (anahtar == 'dolduruldu') ? undefined : deger;
}));
/* degistiriciye gelen anahtar:deger ifti:
: [object Object]
baslik: Conference
katilimci: [object Object],[object Object]
0: [object Object]
adi: Ahmet
1: [object Object]
adi: Mehmet
yer: [object Object]
sayi: 23
*/
degistirici fonksiyonu i ie objeler ve diziler dahil her eyi alr. Tm objelere yinelemeli olarak uygulanr. thisin deeri degistirici ierisinde o anki zellikleri tutar.
lk ar zeldir. Sarc obje vastasyla: {"": tanisma}. Dier bir deyile ilk (anahtar, deger) ifti bo anahtar ile gelir ve deeri hedef objenin tamamdr. Bundan dolay yukardaki rnekte ilk satr: ":[object Object]"'dir.
Fikir degistiriciyi olabildiince gl yapmaktr: Bylece gelen tm objeyi pas geme veya analiz etme gibi imkanlar salanr.
Formatlama: bosluk
JSON.stringify(deger, degistirici, boluk)'n 3. argman formatlamay gzel yapmak iin ka boluk braklmas gerektii bilgisini alr.
nceden, karakter dizisi haline getirilmi objelerin hi boluklar bulunmamaktayd. Eer bunu obje zerinden gndermek istiyorsanz pek nemli deildir. bosluk sadece gzel kt vermek amacyla kullanlr.
Burada bosluk = 2 kullanlmtr, i ie objelerin birka satrda ve objeler arasnda 2 boluk olacak ekilde ayarlamasn syler.
let kullanici = {
adi: "Ahmet",
yas: 25,
roller: {
admin: false,
editor: true
}
};
alert(JSON.stringify(kullanici, null, 2));
/* iki boluk:
{
"adi": "Ahmet",
"yasi": 25,
"roller": {
"admin": false,
"editor": true
}
}
*/
/* JSON.stringify(user, null, 4) iin ise kt aadaki gibi olur:
{
"adi": "Ahmet",
"yasi": 25,
"roller": {
"admin": false,
"editor": true
}
}
*/
bosluk genelde loglama veya gzel kt almak iin kullanlr.
stee gre uyarlanm toJSON
Karakterlerin eviriminde toString metodunun kullanlabileceini daha nce sylemitik. Objeler iin toJSON metodu varsa JSON.stringify arldnda bu otomatik olarak arlr.
rnein:
let oda = {
sayi: 23
};
let toplanti = {
baslik: "Konferans",
tarih: new Date(Date.UTC(2017, 0, 1)),
oda
};
alert( JSON.stringify(toplanti) );
/*
{
"baslik":"Konferans",
"tarih":"2017-01-01T00:00:00.000Z", // (1)
"oda": {"sayi":23} // (2)
}
*/
Grdnz gibi date (1) karaktere dnt. Bunun nedeni date objesinin toJSON metoduna sahip olmasdr.
Eer toJSON metodunu oda objesine uygularsanz:
let oda = {
sayi: 23,
toJSON() {
return this.sayi;
}
};
let toplanti = {
baslik: "Konferans",
oda
};
alert( JSON.stringify(oda) ); // 23
alert( JSON.stringify(toplanti) );
/*
{
"baslik":"Konferans",
"oda": 23
}
*/
Grdnz gibi toJSON hem dorudan ar iin hem de i ie objeler iin kullanlabilir.
JSON.parse
JSON-karakterinin kodlamasn geri evirmek iin ( decode ), JSON.parse adnda dier bir metoda ihtiya vardr.
Yazm:
let deger = JSON.parse(str[, alc]);
- str
- zlecek JSON metni.
- alc
- Opsiyonel function(anahtar,deger) ile her
(anahtar,deger)ifti iin arlacaktr. Bu deerler fonksiyon ierisinde deitirilebilir.
rnein:
// metne evrilmi dizi
let sayilar = "[0, 1, 2, 3]";
sayilar = JSON.parse(sayilar);
alert( sayilar[1] ); // 1
ie objeler iin:
let kullanici = '{ "adi": "Ahmet", "yasi": 35, "admin": false, "arkadaslar": [0,1,2,3] }';
kullanici = JSON.parse(kullanici);
alert( kullanici.arkadaslar[1] ); // 1
JSON gerektii kadar karmak olabilir, ierisinde objeler diziler ve bu objelerin ierisinde objeler diziler olabilir. Tek yapmas gereken formata uymaktr.
Aada elle yazlan JSONda en ok karlalan hatalar sralanmtr. (Bazen test etme amal elle JSON yazlabilir)
let json = `{
adi: "Ahmet", // hata: ki trnak olmadan anahtar yazmak
"soyadi": 'Gngr', // hata: Deerde tek trnak kllanlmtr. Bu ift trnak olmal
'admin': false // hata: Anahtar iin tek trnak kullanlmtr.
"dogumGunu": new Date(2000, 2, 3), // hata: "new" deeri kabul edilmez, sadece deer girilmelidir.
"friends": [0,1,2,3] // hata yok!
}`;
Bunun yannda JSON yorumlara izin vermez. Yorum eklenirse JSON almaz hale gelir.
JSON5 adnda farkl bir format bulunmaktadr. Bu format trnaksz yazma ve yorumlara izin vermektedir. Fakat bu ayr bir ktphanedir ve JSONun artnamesinde bulunmamaktadr.
JSONun daha sk yazma sahip olmasnn nedeni gelitiricilerinin tembel olmas vs deildir. Asl ama ok daha hzl ayrtrma algoritmas uygulayabilmektir.
Alc kullanma
Diyelim ki sunucunuzda tanisma diye bir objeyi metin eklinde tutuyorsunuz.
Aadaki gibi grnecektir:
// baslik: (tanisma basligi), tarih: (tanisma tarihi)
let str = '{"baslik":"Konferans","tarih":"2017-11-30T12:00:00.000Z"}';
imdi bunun tekrar obje haline getirilmesi gerekmektedir. ( deserialize )
JSON.parse kullanarak yapldndan:
let str = '{"baslik":"Konferans","tarih":"2017-11-30T12:00:00.000Z"}';
let tanisma = JSON.parse(str);
alert( tanisma.date.getDate() ); // Hata!
HATA!
tanisma.tarih karakter dizisidir, tarih deil. JSON.parse bu karakter dizisini Date objesine evireceini nasl bilebilir ?
Bunu Alc fonksiyon ile tm deerler olduu gibi alp sadece tarih Date objesi olarak evrilebilir.
let str = '{"baslik":"Konferans","tarih":"2017-11-30T12:00:00.000Z"}';
let tanisma = JSON.parse(str, function(anahtar, deger) {
if (anahtar == 'tarih') return new Date(deger);
return deger;
});
alert( tanisma.tarih.getDate() ); // imdi alyor!
Bu i ie objeler iin de ayn ekilde alr:
let program = `{
"tanismalar": [
{"baslik":"Konferans","tarih":"2017-11-30T12:00:00.000Z"},
{"baslik":"DogumGunu","tarih":"2017-04-18T12:00:00.000Z"}
]
}`;
program = JSON.parse(program, function(anahtar, deger) {
if (anahtar == 'tarih') return new Date(deger);
return deger;
});
alert( program.tanismalar[1].tarih.getDate() ); // alr!
zet
- JSON kendine ait standard olan ve birok programlama dilinde ktphanesi olan bir veri formatdr.
- JSON basit objeleri, dizileri, karakterleri, saylar, boolean deerleri ve
nullu destekler. - JavaScript objeleri seri hale getirmek iin JSON.stringify metodunu ve tekrar obje haline getirmek iin JSON.parse metodunu salar.
- Her iki metod da evirilerde kendinize ait fonksiyonlar kullanmanza olanak verir.
- Eer obje
toJSONmetoduna sahipse,JSON.stringifysrasnda bu metod kullanlr.
Yorumlar
<code>kullannz, birka satr eklemek iin ise<pre>kullann. Eer 10 satrdan fazla kod ekleyecekseniz plnkr kullanabilirsiniz)