Uvod
JSON (JavaScript Object Notation), je tekstualni format za razmenu složenih podataka (u praktičnom smislu - objekata), i u pitanju je format koji podrazumeva da se pojedinačni podaci u okviru JSON objekta zapisuju preko parova ključ-vrednost.
Sam format nalikuje na sintaksu za definisanje objekata u JavaScript-u, jednostavan je za razumevanje, pisanje i čitanje (bilo da čitanje/pisanje obavlja čovek ili računar) i takođe, potpuno je transparentan (podaci zapisani u tekstualnom obliku su, razume se, direktno čitljivi).
Iako JSON jeste ponikao iz jezika JavaScript, podrška za JSON format je odavno prisutna i u brojnim drugim jezicima (PHP, Python, C#, Java, Android ....) i kao takav, JSON u ovom trenutku praktično predstavlja nezvanični standard za razmenu podataka između udaljenih računara (ili, između različitih programa na istom računaru), posebno kada su u pitanju web aplikacije.
Problematika razmene podataka na daljinu
JSON objekti su jednostavni za razumevanje (i mi se naravno nećemo "truditi da ih nepotrebno zakomplikujemo"), ali, prodiskutovaćemo ukratko o problematici razmene podataka u opštem smislu, to jest, o tome zašto se podaci - pogotovo kada je u pitanju razmena između udaljenih računara - tipično ne razmenjuju u izvornom (binarnom) obliku:
- u različitim računarskim programima (koji su projektovani preko različitih programskih jezika), objekti se zapisuju na unapred utvrđen način, * ali, uglavnom se koriste binarni formati (što je logičan i ekonomičan izbor za zapis podataka u okviru jednog sistema)
- binarni formati u različitim programima/informacionim sistemima, jesu (uglavnom), jasni i ekonomični, ali - nisu međusobno usaglašeni
- prenos podataka na daljinu u izvornom (binarnom) obliku, jeste moguć, ali nije praktičan i predstavlja sigurnosni rizik, budući da zapis nije transparentan **
Kada je u pitanju prenos podataka na daljinu - i budući da je format koji se koristi za slanje podataka od servera do klijenta (i obrnuto), ionako običan tekst - format koji za zapisivanje/razmenu složenih objekata takođe koristi običan tekst, predstavlja praktično rešenje.
JSON format (predstavljanje podataka preko ključeva i vrednosti)
Budući da je JSON format sasvim jednostavan, pogledajmo odmah primer:
{
"ime": "Petar",
"prezime": "Marković",
"email": "p_markovic@xyzf.bg.ac.rs",
"datum_rođenja": "06.04.1995.",
"prosek_ocena": 9.21,
"redovan_student": true,
"postdiplomske_studije": false,
"objavljeni_radovi": null
}
Opšte odrednice JSON formata su sledeće:
- celokupan JSON objekat oivičen je vitičastim zagradama
- svaki pojedinačni podatak definisan je preko ključa (primer: "ime") i vrednosti koja je vezana za ključ ("Petar") i od drugih podataka odvojen zarezom *
- tekstualne vrednosti zapisuju se između znakova navoda, ** dok se brojčane vrednosti i drugi podržani osnovni tipovi podataka zapisuju bez znakova navoda (baš onako kako smo i inače navikli u programskim jezicima)
- pored pojedinačnih podataka, ključevi mogu biti vezani i za nizove i složene objekte (kao što ćemo videti u nastavku) ***
Tipovi podataka koji su podržani u JSON objektima su:
- niske (beleže se između znakova navoda)
- brojevi (beleže se bez znakova navoda)
- Boolean vrednosti
true
ilifalse
(beleže se bez znakova navoda) - null (prazan objekat; beleži se bez znakova navoda)
- nizovi i objekti (način beleženja biće objašnjen u nastavku)
Postupak kojim se stanje određenog objekta (ili neke druge strukture podataka), prevodi u JSON format, naziva se serijalizacija (termin koji nas podseća na to da je JSON objekat, "samo niz znakova").
Postupak kojim se od JSON strukture kreira objekat ili neka druga binarna struktura podataka (u određenom programskom jeziku), naziva se deserijalizacija.
Zapisivanje nizova
Ukoliko je neko od svojstava potrebno zapisati kao niz podataka, koriste se uglaste zagrade (baš kao što smo i inače navikli, u velikoj većini programskih jezika):
{
"ime": "Petar",
"prezime": "Marković",
"email": "p_markovic@xyzf.bg.ac.rs",
"datum_rođenja": "06.04.1995.",
"prosek_ocena": 9.21,
"redovan_student": true,
"postdiplomske_studije": false,
"objavljeni_radovi": null,
"kursevi_asistent": [
"Osnove programiranja",
"Uvod u Javu",
"Uvod u Python"
]
}
U gornjem primeru, kursevi na kojima je student angažovan u svojstvu asistenta, dodati su među podatke i predstavljeni kao niz.
Ugnežđavanje složenih podataka
Kako u okviru JSON objekta zapisati podatak koji sam po sebi predstavlja složeni podatak?
Odgovor je: uz poštovanje pravila koja smo već naveli, to jest, kao i svaki drugi par ključ-vrednost:
- ključ (naziv objekta) biće zapisan izmeću znakova navoda
- vrednost će (ovoga puta) biti zapisana kao zaseban (ugnežđeni) JSON objekat
Da pojasnimo preko primera: niska koja sama po sebi predstavlja zaokružen JSON objekat ....
{
"država": "Srbija",
"grad": "Beograd",
"ulica": "Grofa Drakule",
"broj": 41
}
.... lako se može upisati u drugi JSON objekat:
{
"ime": "Petar",
"prezime": "Marković",
"adresa": {
"država": "Srbija",
"grad": "Beograd",
"ulica": "Grofa Drakule",
"broj": 41
},
"email": "p_markovic@xyzf.bg.ac.rs",
"datum_rođenja": "06.04.1995.",
"prosek_ocena": 9.21,
"redovan_student": true,
"postdiplomske_studije": false,
"objavljeni_radovi": null,
"kursevi_asistent": [
"Osnove programiranja",
"Uvod u Javu",
"Uvod u Python"
]
}
(Naravno, uz poštovanje svih do sada navedenih pravila.)
U drugom primeru (u kome ćemo, između ostalog, dodatno objasniti smisao vrednosti null
), osvrnućemo se na situaciju u kojoj student: prelazi na postdiplomske studije, prestaje da bude asistent, i menja adresu (tako da trenutno nisu dostupni podaci o novoj adresi).
U navedenim okolnostima, polje "adresa"
(privremeno) dobija vrednost null
(u smislu: "adresa ne postoji"), polje "postdiplomske_studije"
dobija vrednost true
, a polje "kursevi_asistent"
takođe dobija vrednost null
.
Budući da su se u međuvremenu pojavili i naučni radovi (koje treba uvrstiti), predstavićemo ih kao niz JSON objekata:
{
"ime": "Petar",
"prezime": "Marković",
"adresa": null,
"email": "p_markovic@xyzf.bg.ac.rs",
"datum_rođenja": "06.04.1995.",
"prosek_ocena": 9.21,
"redovan_student": true,
"postdiplomske_studije": true,
"objavljeni_radovi": [
{
"naziv": "Projektovanje baza podataka",
"datum": "09.12.2019.",
"mentor": "Prof. Dr Milan Adamović"
},
{
"naziv": "Open-source prevodioci",
"datum": "21.03.2020.",
"mentor": "Prof. Dr Jelena Zec"
}
]
}
Verujemo da niste iznenađeni ni ovakvim ugnežđavanjem, jer - budući da je moguće da vrednosti u parovima ključ-vrednost budu JSON objekti - svakako nije iznenađujuće ni to što pojedinačni elementi nizova u JSON objektima, takođe mogu biti JSON objekti.
U praksi ....
JSON, kao format za prenos i razmenu podataka (kao što smo već nagovestili), ima dobru podršku u svim popularnim programskim jezicima, a zarad ilustracije ćemo koristiti programske jezike Java i JavaScript i razmotriti jednostavne primere serijalizacije i deserijalizacije.
Primeri u Javi
U programskom jeziku Java, za rad sa JSON objektima se tipično koristi popularna biblioteka GSON
.
Za pretvaranje Java objekta u JSON objekat, prvo je potrebno definisati klasu koja odgovara zahtevima zadatka (zarad preglednosti, nećemo navoditi sva polja) ....
public class Student {
private String ime;
private String prezime;
private String email;
private LocalDate datum_rodjenja;
public Student(String ime, String prezime, String email, int godina_rodjenja) {
this.ime = ime;
this.prezime = prezime;
this.email = email;
this.godina_rodjenja = godina_rodjenja;
}
}
.... potom je potrebno inicijalizovati objekat ....
LocalDate datum_rodjenja = LocalDate.of(1997, 4, 6);
Student student = new Student("Petar", "Marković", "p_markovic@xyzf.bg.ac.rs", datum_rodjenja);
.... posle čega se može kreirati objekat klase GSON
....
Gson gson = new Gson();
String json = gson.toJson(student);
.... preko koga se obavlja serijalizacija objekta klase Student
.
Niska json
sada ima sadržaj nalik na JSON objekat sa slike #1 iz ovog članka (ako želite da sadržaj bude identičan, dodajte i ostala polja i prepravite konstruktor klase), a ono što je najzanimljivije u celoj situaciji, je to da su ključevi automatski dobijeni iz naziva polja klase.
Na jednostavan način (ukoliko je niska pravilno formatirana), možemo 'obrnuti proces', i od JSON objekta dobiti Java objekat (deserijalizacija).
Student student_2 = gson.fromJson(json, Student.class);
Primeri u JavaScript-u
U JavaScript-u stvari (očekivano), funkcionišu na jednostavniji način.
Serijalizacija objekata (JS objekat -> JSON):
let O_1 = {
ime: "Petar",
prezime: "Marković",
prosek_ocena: 9.21,
redovan_student: true,
};
let JSON_1 = JSON.stringify(O_1);
console.log(JSON_1);
Deserijalizacija/parsiranje (JSON -> JS objekat):
let JSON_2 = `
{
"ime": "Petar",
"prezime": "Marković",
"prosek_ocena": 9.21,
"redovan_student": true
}
`;
let O_2 = JSON.parse(JSON_2);
console.log(O_2);
Preko JavaScript-a, lako možete isprobati sve primere iz članka * (i naravno, druge objekte koje možete zamisliti).
Za kraj ....
Čitaocima koji su dodatno zainteresovani za JSON objekte, ostavljamo da samostalno otkriju kako se (u Javi; pri deserijalizaciji), rešava problem koji nastaje kada ključevi u JSON objektu ne odgovaraju poljima klase, kao i to da samostalno (u Javi ili nekom drugom programskom jeziku), napišu klasu kao što je GSON, sa funkcijama za pretvaranje objekata različitih klasa u JSON objekte i obrnuto.
O tome kako se JSON format koristi za razmenu podataka između različitih delova web aplikacija (što je, kao što smo nagovestili na početku, najčešći vid primene JSON formata u ovom trenutku), pisaćemo detaljnije u bliskoj budućnosti, u člancima koji će biti posvećeni implementaciji različitih delova web aplikacija (preko JavaScript-a, PHP-a, Node.JS-a i drugih tehnologija) ....