Format JSON - wprowadzenie
Spis treści
Czym jest JSON?
Programiści (aplikacji webowych), bardzo często mają do czynienia z formatem JSON. W moim przypadku właściwie nie ma dnia bez kontaktu z JSON-em.
JSON to lekki, tekstowy format wymiany danych (choć może być stosowany do innych celów, np. przechowywania konfiguracji), który charakteryzuje się wysoką czytelnością i niskim narzutem - dane zakodowane w postaci JSON zawierają stosunkowo mało znaków nie będących właściwymi danymi - co jest zwłaszcza widoczne porównując odwzorowanie tych samych danych w formatach JSON i XML.
Najczęściej JSON stosowany jest do przesyłania danych przy pomocy protokołu HTTP pomiędzy maszynami połączonymi siecią. Serwery aplikacji webowych bardzo często odpowiadają na żądania klientów zwracając im dane zakodowane w postaci JSON. Nie jest niczym niespotykanym komunikacja w przeciwnym kierunku, gdy to klient przesyła do serwera dane zakodowane JSON'em.
Można więc śmiało powiedzieć, że JSON over HTTP to swoisty klej łączący serwery i klienty aplikacji webowych.
Nazwa JSON, rozwijana jako JavaScript Object Notation, z jednej strony znakomicie oddaje czym jest JSON. Jeśli miałeś/aś już do czynienia ze strukturami danych, takimi jak obiekty i tablice w języku JavaScript, zauważysz uderzające podobieństwo.
Z drugiej strony, nazwa może nieco wprowadzać w błąd, sugerując pewien związek z JavaScriptem.
JSON to format całkowicie niezależny od języka programowania, a możliwość kodowania do postaci JSON natywnych dla danego języka struktur danych (jak obiekty czy tablice) oraz dekodowania danych z postaci JSON do natywnych struktur danych języka, istnieje dla każdego popularnego języka programowania, czy to w postaci wbudowanych funkcji, czy też dodatkowych bibliotek.
Należy jednak uczciwie przyznać, że jeśli klientem jest przeglądarka internetowa, (de)kodowanie JSONa na kliencie faktycznie odbywa się w większości przypadków przy pomocy JavaScriptu.
Pamiętajmy jednak, że serwer musi być w stanie realizować te same zadania związane z (de)kodowaniem danych, niezależnie czy jest napisany w Javie, PHP, GO, Ruby, Pythonie czy innych.
Typy wartości
JSON jest bardzo prostym formatem i wspiera zaledwie kilka typów wartości. Wyróżniamy typy proste (prymitywne) oraz typy złożone.
Typy proste - łańcuchy znaków
Ciągi znaków (łańcuchy, stringi) - dowolny ciąg znaków objęty cudzysłowem może być wartością w formacie JSON, na przykład "To jest poprawny łańcuch znaków"
.
Znaki cudzysłowia okalające łańcuch muszą być podwójne (znak "
) - pojedyncze (znak '
są niepoprawne!).
Niektóre znaki specjalne oraz choćby sam cudzysłów, muszą być poprzedzone znakiem ucieczki (ang. escaping), czyli znakiem \
(backslash).
Przykładowo, żeby zakodować tekst zawierający w sobie tytuł filmu objęty w cudzysłów, wewnętrzne znaki cudzysłowia muszą być poprzedzone znakami ucieczki: "Mój ulubiony film to \"Gorączka\". Świetna obsada i scenariusz."
.
Niepowodzeniem skończy się próba nadania w formacie JSON wartości: "Mój ulubiony film to "Gorączka". Świetna obsada i scenariusz."
Typy proste - liczby
Liczby: mogą być całkowite, np. 5
lub 18313088
.
Zauważ, że liczby nie są ujęte w cudzysłów. Oczywiście wartość "5"
jest również poprawną wartością w formacie JSON, ale jest ona... ciągiem znaków.
Zapamiętaj, to bardzo ważne - liczby to liczby, a łańcuchy znaków to łańcuchy znaków.
Zwykle typ danych ma kluczowe znaczenie dla poprawnej interpretacji i przetwarzania danych.
Różne języki programowania na różny sposób podchodzą do źle typowanych danych, ale nawet jeśli pracujesz w języku, który jest bardzo tolerancyjny, zawsze dbaj o poprawne typy danych w tworzonych JSONach. Nie chcesz w wyniku operacji 3 + 12
otrzymać rezultatu 312
(co jest wysoce prawdopodobne, jeśli przez niedbałość twój JSON będzie zawierał wartości "3"
oraz "12"
zamiast 3
i 12
).
Liczby mogą też być zmiennoprzecinkowe (z częścią ułamkową), np. 12.4
albo 0.999
.
Liczby całkowite i zmiennoprzecinkowe to ten sam typ danych. Obowiązują te same reguły - brak okalającego cudzysłowia. Do odzielenia części ułamkowej konieczne jest stosowanie znaku kropki (.
) a nie przecinka (,
).
Typy proste - wartości logiczne
Prosta sprawa, wartośc logiczna może mieć jedną z dwóch wartości: true
(prawda) lub false
(fałsz).
Zapamiętaj: wartości logiczne nie są ujęte w cudzysłów!
Podobnie jak z liczbami, cudzysłów robi potężną różnicę.
Owszem, "false"
to poprawna wartość w JSON, ale znowu - jest to łańcuch znaków, a nie wartość logiczna.
Prosta ewaluacja wartości logicznej takiej wartości łańcuchowej (o ile jest dozwolona w używanym języku programowania mimo oczywistej niezgodności typów), wbrew oczekiwaniom, zaowocuje wartością true
(gdyż łańcuch jest niepusty).
Typy proste - wartość pusta
Wartość pusta - null
.
Używana to wskazania braku ustalonej wartości.
Podobnie jak z wartościami logicznymi i liczbami - nie używamy wokół wartości null
znaków cudzysłowia. "null"
to zdecydowanie niepusta wartość - to jasno określona wartość - łańcuch 4 znaków.
Typy złożone - tablice
Tablice są strukturami zawierającymi uporządkowane kolekcje wartości (kolejność wartości ma znaczenie).
Wartości wewnątrz tablic rozdzielone są przecinkami. Samą tablice zapisuje się przy pomocy nawiasów kwadratowych (znaki [
i ]
).
W formacie JSON jedna tablica może zawierać wartości różnych typów (innymi słowy nie wszystkie wartości wewnątrz jednej tablicy muszą być tego samego typu, choć oczywiście mogą).
Wartości wewnątrz tablic mogą być zarówno typów prostych jaki złożonych (co znaczy, że wartością wewnątrz tablicy może być obiekt albo inna tablica - innymi słowy tablice można w sobie zagnieżdżać).
Tablica może być pusta (nie zawiera żadnych elementów): []
.
Tablica zawierająca tylko liczby całkowite: [1, 5, 10000, -21]
.
Tablica zawierająca wartości różnych typów (w tym inną tablicę): [1, -1, "Łańcuch", false, [78, "Hello world!"], 12]
.
Po ostatniej wartości tablicy nie stosuje się przecinka!
Wartości w tablicy mogą się powtarzać (całkowicie poprawnym jest np. [0, 1, 0, 0, 0, 1, 1]
).
Typy złożone - obiekty
Obiekty są strukturami, w których wartości są przypisane kluczom będącymi łańcuchami znaków.
Każda para klucz - wartość jest oddzielona od sąsiednich przecinkami (po ostatniej parze nie stosuje się przecinka).
Klucz i przypisana mu wartość oddzielone są dwukropkiem (:
).
Obiekty zapisywane są przy pomocy nawiasów klamrowych (znaki {
oraz }
).
Wartościami w obiekcie mogą być wartości dowolnych typów prostych oraz złożonych (wartością wewnątrz obiektu może być inny obiekt lub tablica).
Obiekty JSON odpowiadają strukturom znanym w językach programowania jako tablice asocjacyjne, tablice z hashowaniem bądź jako po prostu obiekty.
Obiekt może być pusty: {}
.
Obiekt opisujący osobę:
{"first_name": "John", "last_name": "Cantucci", "dob": "1969-03-21", "nicknames": ["Spyder", "Spider", "Johnny Boy"], "felonies": 7, "misdemeanours": 21}
.
Klucze w obrębie jednego obiektu muszą być unikalne (nie mogą się powtarzać), natomiast wartości przypisane różnym kluczom mogą być takie same.
JSON w praktyce
Konieczność ręcznego pisania JSONa zachodzi bardzo rzadko lub wcale - do formatu JSON kodujemy dane zapisane w strukturach danych istniejących w językach programowania, z którymi pracujemy przy pomocy pojedynczej instrukcji.
Proces kodowania nazywany bywa czasem serializacją lub marshallingiem.
Dekodowanie danych z formatu JSON do właściwych dla danego języka programowania struktur również odbywa się automatycznie.
Dekodowanie bywa czasem nazywana deserializacją bądź unmarshallingiem.
Biegłość w czytaniu danych zapisanych w formacie JSON jest jednak bardzo przydatna. Programiści aplikacji webowych przyglądają się danym zapisanym w formacie JSON każdego dnia, czasem szukając błędu po stronie kodowania, czasem po prostu przyglądając się strukturze danych, by odpowiednią ją odwzorować strukturami, do których nastąpi deserializacja.
Na szczęście JSON jest bardzo czytelny i najważniejsze jest po prostu dobrze rozumieć jego strukturę. Czytanie niesformatowanego JSONa, w którym wszystkie dane zapisane są w jednej linii tekstu, jest jednak dosyć kłopotliwe.
Dopiero poprawnie sformatowane dane stają się bardzo łatwe do odczytania.
Powtórzmy przykład obiektu opisującego osobę: {"first_name": "John", "last_name": "Cantucci", "dob": "1969-03-21", "nicknames": ["Spyder", "Spider", "Johnny Boy"], "felonies": 7, "misdemeanours": 21}
.
Te same dane po sformatowaniu (zastosowaniu nowych linii i odpowiednich dla poziomu zagłębienia wcięć) stają się bardzo czytelne:
{
"first_name": "John",
"last_name": "Cantucci",
"dob": "1969-03-21",
"nicknames": ["Spyder", "Spider", "Johnny Boy"],
"felonies": 7,
"misdemeanours": 21
}
Sama tablica nicknames
dodatkowo może być sformatowana:
{
"first_name": "John",
"last_name": "Cantucci",
"dob": "1969-03-21",
"nicknames": [
"Spyder",
"Spider",
"Johnny Boy"
],
"felonies": 7,
"misdemeanours": 21
}
Co istotne, znaki pomagające zwiększyć czytelność dodatkowym formatowaniem (a więc znaki nowych linii, spacje lub tabulatory) nie wpływają na wartości zapisane w JSONie.
Zwróć uwagę, że przy formatowaniu żadne klucze ani wartości nie zostały zmienione - wyłącznie pomiędzy nim, oraz między nimi a nawiasami określającymi obiekty i tablice wstawiono białe znaki (spacje, nowe linie).
Wszystkie 3 przykłady są równoważne, czyli zawierają dokładnie te same dane.
Jak sformatować dane JSON jeśli chcemy je przeanalizować, a trafiły do nas "skondensowane"?
Być może w Twoim edytorze (IDE) jest opcja lub wtyczka to wyświetlania danych JSON w postaci czytelnej. W razie czego - zawsze możesz skorzystać z narzędzia online, jak choćby JSON Lint.
Po prostu wklej dane JSON w pole tekstowe i wciśnij przycisk "Validate JSON" poniżej.
Tak właściwie jest to walidator JSONa, sprawdzi więc, czy podane dane stanowią poprawny zapis JSON. Jeśli nie - wyświetlony zostanie błąd, jeśli dane są poprawne, zostaną wyświetlone z zastosowaniem czytelnego formatowania.
Zwykle dane przekazywane przy pomocy JSON to obiekty lub ewentualnie tablice. Zwróć uwagę, że to jedyne sposoby, żeby przesłać więcej niż jedną wartość (każda pojedyncza wartość jest poprawnym JSONem, ale już dwie rozdzielone przecinkiem są niedozwolone, oczywiście o ile nie są wewnątrz tablicy).
Właściwie można powiedzieć, że poprawne dane JSON to jedna wartość, czy to typu prostego, czy złożonego, nawet pusta.
Zwykle więc to okalający wszystkie dane obiekt jest zorganizowany w taki sposób, by umożliwić łatwy odczyt danych odbiorcy (konsumentowi).
Przykładowo, JSON zawierający listę artykułów wyświetlaną na głównej stronie bloga, mógłby być tablicą, zawierającą obiekty, z których każdy opisuje jeden artykuł, np.:
[
{
"title": "Nauka JSONa",
"author": "Olek",
"published_at": "2021-07-27 15:12:04"
},
{
"title": "Pracujemy z Gitem",
"author": "Olek",
"published_at": "2021-07-14 00:21:33"
},
{
"title": "Pierwsze kroki w terminalu",
"author": "Jan",
"published_at": "2019-12-23 19:58:31"
}
]