JavaScript · JSON

JSON i obsługa błędów w JavaScript — lekcja z przykładowymi danymi

JSON.parse i stringify, try, catch, finally oraz ?. i ?? na przykładowych tekstach JSON. Trzy zadania bez połączenia z internetem.

45 minutPoziom podstawowyPliki i rozwiązania

Materiał redakcyjny TablicaPro · liceum i technikum

try {
  JSON.parse('{zly json');
} catch (blad) {
  console.log(blad.name);
}
SyntaxError
Błąd obsłużony, program działa dalej.

Dane z internetu zwykle przychodzą jako tekst w formacie JSON. Zanim je pokażemy na stronie, trzeba je zamienić na obiekty, a to się może nie udać — gdy odpowiedź jest uszkodzona albo pusta. Na lekcji uczniowie pracują na przykładowych tekstach JSON (bez łączenia się z internetem), zamieniają je na obiekty i obsługują błędy.

Scenariusz jest przeznaczony na 45 minut dla klasy znającej obiekty i tablice — na przykład po lekcji o obiektach. Pobieranie danych funkcją fetch jest tematem osobnej lekcji; tu ćwiczymy to, co następuje po pobraniu.

Przygotowanie stanowisk

Potrzebna jest przeglądarka z konsolą (F12) i edytor tekstu. Rozpakuj pakiet z sekcji materiałów do osobnego folderu. W folderze start jest index.html (nie zmieniasz go) oraz app.js z funkcją pokaz, która wypisuje tekst w konsoli i na stronie. Po zapisaniu app.js odśwież stronę. Gotowe rozwiązanie jest w folderze rozwiazanie. Serwer i Node.js nie są wymagane.

Cele i plan lekcji

Po zajęciach uczeń potrafi:

  • zamienić tekst JSON na obiekt (JSON.parse) i obiekt na tekst (JSON.stringify);
  • wskazać, które wartości nie trafiają do JSON (funkcje, undefined);
  • obsłużyć błędny JSON blokiem try ... catch ... finally;
  • użyć operatorów ?. i ?? do bezpiecznego odczytu zagnieżdżonych danych.
CzasPraca na lekcji
0–5 minProblem: odpowiedź serwera jako tekst
5–15 minJSON.parse i JSON.stringify
15–22 mintry, catch, finally, ?., ??
22–37 minTrzy zadania samodzielne
37–42 minOmówienie błędów
42–45 minPytania kontrolne

JSON

JSON (*JavaScript Object Notation*) to tekstowy format danych: obiekty w klamrach { "klucz": wartość }, tablice w nawiasach [ ... ], a wartości to teksty, liczby, true, false i null. Klucze i teksty muszą mieć cudzysłowy podwójne — zapis {a:1} czy apostrofy nie są poprawnym JSON-em. JSON.parse(tekst) zamienia tekst na obiekt, a JSON.stringify(obiekt) — odwrotnie; funkcje i wartości undefined są przy tym pomijane. Połączenie JSON.parse(JSON.stringify(x)) tworzy głęboką kopię danych.

Błędy

JSON.parse dla niepoprawnego tekstu zgłasza błąd SyntaxError. Nieobsłużony zatrzymuje skrypt, dlatego parsowanie opakowujemy w try ... catch (blad) { ... }; blok finally wykona się zawsze. Do odczytu głęboko zagnieżdżonych danych służy operator ?. (zwraca undefined, gdy po drodze czegoś brak, zamiast zgłaszać błąd), a ?? podaje wartość domyślną, gdy wynik to null lub undefined.

Zadania

Zadanie 1. parse i stringify. Zamień tekst {"imie":"Ola","klasa":2,"oceny":[4,5,3]} na obiekt, wypisz imię, klasę i liczbę ocen, a potem zamień obiekt z powrotem na tekst. Sprawdź, co zrobi JSON.stringify z właściwością undefined i metodą.

Zadanie 2. Błędny JSON. Napisz funkcję wczytaj(napis) zwracającą obiekt albo null dla błędnego tekstu. Sprawdź {"a":1}, {a:1}, pusty tekst i [1,2]. Pokaż try ... catch ... finally dla tekstu {zly json.

Zadanie 3. Bezpieczny odczyt i kopia. Dla odpowiedzi {"uczen":{"imie":"Ola"},"oceny":[]} odczytaj imię ucznia, nieistniejącego nauczyciela (?.) i wartość domyślną (??). Zrób głęboką kopię i zmień w niej imię, żeby pokazać, że oryginał się nie zmienił.

Dla chętnych: sprawdź, co wypisze JSON.stringify(new Date(0)) i dlaczego daty są w JSON zapisywane jako tekst.

Rozwiązanie i wyniki

function pokaz(...czesci) {
  const tekst = czesci.join(" ");
  console.log(tekst);
  document.querySelector("#wynik").textContent += tekst + "\n";
}

// Zadanie 1
const tekst = '{"imie":"Ola","klasa":2,"oceny":[4,5,3]}';
const dane = JSON.parse(tekst);
pokaz(dane.imie, dane.klasa, dane.oceny.length);
pokaz(JSON.stringify(dane));
pokaz(JSON.stringify({ a: 1, b: [true, null], c: undefined, d() {} }));

// Zadanie 2
function wczytaj(napis) {
  try {
    return JSON.parse(napis);
  } catch (blad) {
    return null;
  }
}
pokaz(wczytaj('{"a":1}').a, String(wczytaj("{a:1}")), String(wczytaj("")), wczytaj("[1,2]").length);
try {
  JSON.parse("{zly json");
} catch (blad) {
  pokaz("Blad:", blad.name);
} finally {
  pokaz("Koniec");
}

// Zadanie 3
const odpowiedz = JSON.parse('{"uczen":{"imie":"Ola"},"oceny":[]}');
pokaz(odpowiedz.uczen?.imie, String(odpowiedz.nauczyciel?.imie), odpowiedz.nauczyciel?.imie ?? "brak");
pokaz(odpowiedz.oceny[0]?.wartosc ?? "bez ocen");
const kopia = JSON.parse(JSON.stringify(odpowiedz));
kopia.uczen.imie = "Ewa";
pokaz(odpowiedz.uczen.imie, kopia.uczen.imie);

Program wypisze:

Ola 2 3
{"imie":"Ola","klasa":2,"oceny":[4,5,3]}
{"a":1,"b":[true,null]}
1 null null 2
Blad: SyntaxError
Koniec
Ola undefined brak
bez ocen
Ola Ewa

Typowe błędy

ObjawCo sprawdzić
SyntaxError: Unexpected token w JSON.parseKlucze bez cudzysłowów, apostrofy zamiast cudzysłowów lub przecinek na końcu.
Program zatrzymuje się na błędnym JSONBrak try ... catch wokół JSON.parse.
TypeError: Cannot read properties of undefinedOdczyt zagnieżdżonej właściwości bez ?..
Funkcja zniknęła po stringifyJSON nie przechowuje funkcji ani undefined.
Kopia też się zmieniaPrzypisanie kopia = oryginal kopiuje odwołanie; użyj JSON.parse(JSON.stringify(...)).
?? zwraca 0 jako wartość domyślnąOperator ?? reaguje tylko na null i undefined, nie na 0; do wartości fałszywych służy ``.

Pytania kontrolne i punktacja

  1. Dlaczego {a:1} nie jest poprawnym JSON-em?
  2. Co zwróci obiekt.nauczyciel?.imie, gdy nauczyciel nie istnieje?
  3. Kiedy wykona się blok finally?

Odpowiedzi: Klucze w JSON muszą być w podwójnych cudzysłowach. undefined. Zawsze — niezależnie od tego, czy wystąpił błąd.

Proponowana punktacja (razem 10 punktów): zadanie 1 — parse 1 pkt, stringify 1 pkt, uwaga o undefined i metodzie 1 pkt; zadanie 2 — funkcja wczytaj z try/catch 2 pkt, cztery przypadki 1 pkt, finally 1 pkt; zadanie 3 — ?. 1 pkt, ?? 1 pkt, głęboka kopia 1 pkt. Zadanie dla chętnych nie jest wymagane do pełnej oceny.

Materiały do pobrania

Rozpakuj ZIP przed otwarciem plików. Materiały są dostępne bez logowania; publiczne rozwiązanie służy nauce i samodzielnemu sprawdzeniu, a nie poufnemu sprawdzianowi.

Co dalej?

Następny krok to pobieranie danych funkcją fetch i wyświetlanie ich na stronie. Ten materiał rozwija dział o danych w kursie JavaScript w TablicaPro, gdzie znajdziesz prezentacje, ćwiczenia i testy do prowadzenia lekcji.

Źródła techniczne: JSON w MDN oraz try...catch. Zobacz też lekcję o DOM w JavaScript.

Poprowadź kolejne lekcje JavaScript

Pełny kurs: prezentacje, ćwiczenia i testy do pracy z klasą.

Kup dostęp do kursu JavaScript →

Zobacz program kursu