JSON to tekst, a nie obiekt
JSON (JavaScript Object Notation) to format tekstowy do wymiany danych. Wygląda jak literał obiektu JavaScript, ale jest stringiem, czyli ciągiem znaków, który możesz wysłać przez sieć, zapisać do pliku albo wkleić do konfiguracji.
// A JavaScript object - a live value in memory.
const user = { name: "Rosa", age: 30 };
// JSON - a string of text that represents the same data.
const json = '{"name":"Rosa","age":30}';
Łatwo je pomylić, bo wyglądają podobnie. Model myślowy, który pomaga je rozróżniać: obiekty żyją w twoim programie, a JSON to ich postać w drodze na zewnątrz. Zamieniasz jedno na drugie dwiema funkcjami: JSON.stringify (obiekt → string) i JSON.parse (string → obiekt).
JSON.stringify: z obiektu na string
Zamień dowolną wartość JavaScript na jej reprezentację JSON:
Wynik to jednoliniowy string bez spacji: zwarty, idealny do przesyłania przez sieć. Sprawdzenie typeof to potwierdza: string, a nie object.
Dla czytelności podczas debugowania przekaż dwa dodatkowe argumenty. Drugi to replacer (za chwilę do niego dojdziemy), a przekazanie null oznacza „uwzględnij wszystko”. Trzeci to wcięcie:
To standardowa forma ładnego formatowania. Używaj 2 lub 4 spacji, tak jak robi to większość narzędzi.
JSON.parse: ze stringa na obiekt
Operacja odwrotna: bierzesz string JSON i dostajesz z powrotem wartość JavaScript.
Po sparsowaniu masz do czynienia ze zwykłym obiektem: dostęp przez kropkę, przez nawiasy kwadratowe, metody tablicowe i cała reszta.
JSON.parse jest wybredny. Wszystkie poniższe wywołania rzucają SyntaxError:
JSON.parse("{name: 'Rosa'}"); // unquoted key, single quotes
JSON.parse('{"name": "Rosa",}'); // trailing comma
JSON.parse("// a comment\n{}"); // comments aren't allowed
JSON.parse(""); // empty string
Zawsze gdy dane przychodzą spoza twojego programu, czyli z odpowiedzi fetch, z pliku czy od użytkownika, owiń parsowanie w try/catch:
Wartości, które nie przetrwają podróży w obie strony
JSON obsługuje sześć typów wartości: stringi, liczby, wartości logiczne, null, tablice i zwykłe obiekty. Wszystko inne w JavaScript zostaje usunięte, przekształcone albo powoduje błąd.
Co się dzieje:
- Funkcje i
undefinedsą po cichu usuwane z obiektów. W tablicach stają sięnull, bo tablice w JSON nie mogą mieć dziur. - Obiekty
Datesą serializowane do stringa ISO przez ich metodętoJSON. Parsowanie oddaje ci string, a nieDate. BigIntrzucaTypeError. Liczby w JSON nie mają odpowiednika.Map,Seti odwołania cykliczne też nie działają od razu.
Problem z odtwarzaniem Date rozwiązuje funkcja reviver w JSON.parse:
Reviver uruchamia się dla każdej pary klucz/wartość i pozwala przekształcać wartości podczas wczytywania.
Replacer: filtrowanie tego, co trafia do JSON
Drugi argument JSON.stringify pozwala kontrolować, co znajdzie się w wyniku. Przekaż tablicę kluczy, żeby dopuścić tylko je:
Albo przekaż funkcję z dowolną logiką: usuwaj pola, maskuj wartości, przekształcaj je w locie:
Zwrócenie undefined usuwa klucz. Zwrócenie dowolnej innej wartości go zastępuje.
Dostosowywanie przez toJSON
Jeśli obiekt ma metodę toJSON, JSON.stringify ją wywołuje i serializuje zwróconą wartość. W ten sposób Date kontroluje własny format i ty możesz użyć tego samego mechanizmu:
Świetne dla klas, które chcą mieć spójny publiczny kształt, niezależnie od tego, kto je serializuje.
Głęboka kopia (stary trik i lepszy sposób)
Przez lata JSON.parse(JSON.stringify(obj)) było jednolinijkowcem do głębokiego kopiowania zwykłego obiektu:
To działa, dopóki obiekt zawiera tylko wartości bezpieczne dla JSON. Daty, mapy i funkcje to psują (zobacz problemy opisane wyżej).
Nowoczesny JavaScript ma structuredClone, który obsługuje daty, Map, Set, tablice typowane i odwołania cykliczne:
Sięgaj po structuredClone, kiedy tylko możesz. Trik JSON.parse(JSON.stringify(...)) zachowaj na szybkie, prowizoryczne kopie prostych danych.
Realistyczny przykład: pobieranie i parsowanie
Najczęściej zetkniesz się z JSON przy HTTP. fetch nie parsuje za ciebie JSON: wywołujesz .json() na odpowiedzi (co w praktyce jest JSON.parse na treści odpowiedzi):
Wysyłanie JSON to operacja odwrotna: przepuść treść przez JSON.stringify i ustaw nagłówek Content-Type.
await fetch("/api/users", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name: "Rosa", age: 30 }),
});
Te dwa wzorce pokrywają zdecydowaną większość pracy z JSON w prawdziwych projektach.
Dalej: optional chaining
Sparsowany JSON często ma opcjonalne pola: user.address.city, które może nie istnieć, albo response.data.items, którego może brakować. Bezpieczny dostęp do głęboko zagnieżdżonych właściwości bez wysypywania programu zapewnia optional chaining (?.) i o nim jest następna strona.
Najczęściej zadawane pytania
Czym różni się JSON od obiektu JavaScript?
JSON to format tekstowy: string, który wygląda jak literał obiektu JavaScript, ale ma ostrzejsze zasady. Klucze muszą być w cudzysłowach podwójnych, stringi też, a wartości ograniczają się do stringów, liczb, wartości logicznych, null, tablic i zwykłych obiektów. Obiekt JavaScript to żywa wartość w pamięci, która może przechowywać funkcje, undefined, instancje Date i wszystko inne.
Jak zamienić obiekt JavaScript na JSON?
Wywołaj JSON.stringify(obj). Funkcja przechodzi po obiekcie i zwraca string JSON. Przekaż trzeci argument, na przykład JSON.stringify(obj, null, 2), żeby ładnie sformatować wynik z wcięciem na 2 spacje. Funkcje i wartości undefined są usuwane z obiektów, a w tablicach zamieniają się w null.
Dlaczego JSON.parse rzuca błąd?
JSON.parse jest rygorystyczny: przecinki na końcu, pojedyncze cudzysłowy, klucze bez cudzysłowów i komentarze powodują SyntaxError. Owijaj wywołanie w try/catch zawsze, gdy dane pochodzą z żądania sieciowego, pliku lub od użytkownika, czyli wszędzie tam, gdzie string może nie być poprawnym JSON.
Czy JSON.stringify zachowuje daty?
Nie. Date zamienia się w string ISO, taki jak "2026-01-15T10:30:00.000Z". Gdy z powrotem użyjesz JSON.parse, dostaniesz ten string, a nie obiekt Date. Jeśli potrzebujesz dat, użyj argumentu reviver w JSON.parse, żeby zamienić stringi ISO z powrotem na instancje Date.