Lekcja 19: JSON - Praca z Danymi w Formacie JSON
Witaj w dziewiętnastej lekcji kursu PHP! W dzisiejszym świecie aplikacji internetowych wymiana danych między różnymi systemami i technologiami jest codziennością. Jednym z najpopularniejszych formatów używanych do tego celu jest JSON (JavaScript Object Notation). Jest to lekki, tekstowy format wymiany danych, czytelny zarówno dla ludzi, jak i łatwy do parsowania przez maszyny. PHP oferuje wbudowane, wydajne funkcje do pracy z JSON, które pozwalają na łatwe kodowanie danych PHP do formatu JSON oraz dekodowanie danych JSON na zmienne PHP. W tej lekcji dokładnie przyjrzymy się formatowi JSON, jego składni oraz sposobom jego obsługi w PHP.
Co to jest JSON?
JSON, czyli JavaScript Object Notation, został pierwotnie wywiedziony z języka JavaScript (konkretnie ze sposobu zapisu literałów obiektów i tablic w JavaScript), ale obecnie jest formatem niezależnym od języka programowania. Jego prostota, czytelność i łatwość implementacji parserów sprawiły, że stał się de facto standardem w wielu obszarach, szczególnie w komunikacji z API webowymi (REST API).
Kluczowe cechy JSON:
- Tekstowy format: Dane JSON są reprezentowane jako zwykły tekst, co ułatwia ich przesyłanie i przechowywanie.
- Czytelny dla człowieka: Składnia JSON jest stosunkowo prosta i przypomina strukturę danych znaną z wielu języków programowania.
- Łatwy do parsowania przez maszyny: Większość języków programowania, w tym PHP, posiada wbudowane biblioteki do efektywnego parsowania i generowania JSON.
- Niezależny od języka: Chociaż nazwa sugeruje JavaScript, JSON jest uniwersalnym formatem wymiany danych.
- Lekki: W porównaniu do innych formatów, takich jak XML, JSON jest zazwyczaj bardziej zwięzły, co oznacza mniejszy narzut danych przy transmisji.
Podstawowa Składnia JSON
JSON opiera się na dwóch podstawowych strukturach:
- Kolekcja par nazwa/wartość (Obiekt): Jest to nieuporządkowany zbiór par klucz-wartość. W JSON obiekt jest otoczony nawiasami klamrowymi
{}. Klucze muszą być stringami (ujęte w podwójne cudzysłowy), a wartości mogą być dowolnego typu JSON. Pary klucz-wartość są oddzielone przecinkami, a klucz od wartości dwukropkiem. Odpowiada to obiektom w JavaScript lub tablicom asocjacyjnym w PHP. - Uporządkowana lista wartości (Tablica): Jest to uporządkowana sekwencja wartości. W JSON tablica jest otoczona nawiasami kwadratowymi
[]. Wartości są oddzielone przecinkami i mogą być dowolnego typu JSON. Odpowiada to tablicom indeksowanym w PHP lub tablicom w JavaScript.
Typy Danych w JSON:
- String (Ciąg znaków): Sekwencja znaków Unicode, ujęta w podwójne cudzysłowy (
" "). Znaki specjalne, takie jak cudzysłów, backslash, muszą być poprzedzone znakiem ucieczki (np.\",\\). - Number (Liczba): Liczba całkowita lub zmiennoprzecinkowa. Nie jest ujmowana w cudzysłowy. (np.
123,-42,3.14159,1.2e+10). - Boolean (Wartość logiczna): Może przyjmować wartość
truelubfalse(bez cudzysłowów). - Array (Tablica): Uporządkowana lista wartości, ujęta w
[]. - Object (Obiekt): Nieuporządkowana kolekcja par klucz-wartość, ujęta w
{}. null: Reprezentuje pustą wartość (bez cudzysłowów).
Przykład struktury JSON:
{
"imie": "Jan",
"nazwisko": "Kowalski",
"wiek": 30,
"czyAktywny": true,
"adres": {
"ulica": "Kwiatowa",
"numerDomu": "10A",
"miasto": "Warszawa",
"kodPocztowy": "01-234"
},
"jezyki": [
"polski",
"angielski"
],
"ostatnieLogowanie": null
}
W powyższym przykładzie widzimy obiekt główny z kluczami takimi jak "imie", "nazwisko", "adres" (którego wartością jest kolejny obiekt), "jezyki" (którego wartością jest tablica stringów) oraz "ostatnieLogowanie" z wartością null.
Praca z JSON w PHP
PHP dostarcza dwie główne funkcje do pracy z JSON, dostępne od PHP 5.2.0, które są częścią domyślnej konfiguracji PHP (nie wymagają instalacji dodatkowych rozszerzeń, chyba że PHP zostało skompilowane z opcją --disable-json).
Kodowanie Danych PHP do JSON - Funkcja json_encode()
Funkcja json_encode() służy do konwersji zmiennej PHP (najczęściej tablicy lub obiektu) na jej reprezentację w formacie JSON (string).
Składnia: string|false json_encode(mixed $value, int $flags = 0, int $depth = 512)
$value: Wartość PHP do zakodowania. Może to być dowolny typ danych z wyjątkiem zasobów (resource). Wszystkie stringi muszą być zakodowane w UTF-8.$flags(opcjonalny): Maska bitowa składająca się z różnych stałych, które modyfikują sposób kodowania. Najważniejsze z nich to:JSON_HEX_TAG: Wszystkie znaki<i>są konwertowane na\u003Ci\u003E. Użyteczne, gdy JSON ma być osadzony w HTML.JSON_HEX_AMP: Wszystkie znaki&są konwertowane na\u0026.JSON_HEX_APOS: Wszystkie znaki'(apostrof) są konwertowane na\u0027.JSON_HEX_QUOT: Wszystkie znaki"(cudzysłów) są konwertowane na\u0022.JSON_FORCE_OBJECT: Wymusza, aby wyjściem był obiekt JSON ({}) nawet jeśli wejściem jest pusta tablica lub tablica indeksowana (która normalnie zostałaby zakodowana jako tablica JSON[]).JSON_NUMERIC_CHECK: Koduje numeryczne stringi jako liczby. (Uwaga: może prowadzić do utraty danych, jeśli string nie jest poprawną liczbą lub jest zbyt duży).JSON_PRETTY_PRINT(od PHP 5.4.0): Formatuje wyjściowy JSON w sposób czytelny dla człowieka, dodając wcięcia i nowe linie. Bardzo przydatne do debugowania.JSON_UNESCAPED_SLASHES(od PHP 5.4.0): Nie poprzedza ukośników (/) znakiem ucieczki (\).JSON_UNESCAPED_UNICODE(od PHP 5.4.0): Koduje wielobajtowe znaki Unicode bezpośrednio (np. "zażółć gęślą jaźń") zamiast jako sekwencje\uXXXX. Wymaga, aby dane wejściowe były w UTF-8.JSON_PARTIAL_OUTPUT_ON_ERROR(od PHP 5.5.0): Jeśli wystąpi błąd podczas kodowania (np. nieobsługiwany typ), próbuje zakodować część danych, która jest poprawna, zamiast zwracaćfalse.JSON_PRESERVE_ZERO_FRACTION(od PHP 5.6.6): Zapewnia, że liczby zmiennoprzecinkowe będą zawsze kodowane jako liczby zmiennoprzecinkowe, nawet jeśli część ułamkowa wynosi zero (np.1.0zamiast1).JSON_THROW_ON_ERROR(od PHP 7.3.0): Zamiast zwracaćfalsei ustawiać błąd globalny (json_last_error()), rzuca wyjątekJsonExceptionw przypadku błędu. To preferowany sposób obsługi błędów w nowoczesnym PHP.
$depth(opcjonalny, od PHP 5.3.0): Maksymalna głębokość zagnieżdżenia struktur danych do zakodowania. Domyślnie 512.
Funkcja zwraca string JSON w przypadku sukcesu lub false w przypadku błędu (chyba że użyto JSON_THROW_ON_ERROR).
<?php
// Przykład 1: Prosta tablica asocjacyjna
$dane_uzytkownika_php = [
"id" => 101,
"imie" => "Anna",
"email" => "anna.nowak@example.com",
"tagi" => ["php", "webdev", "kurs"]
];
$json_string = json_encode($dane_uzytkownika_php);
echo "<h3>Prosta tablica asocjacyjna:</h3>";
echo "<pre>" . htmlspecialchars($json_string) . "</pre>";
// Wynik: {"id":101,"imie":"Anna","email":"anna.nowak@example.com","tagi":["php","webdev","kurs"]}
// Przykład 2: Z flagą JSON_PRETTY_PRINT
$json_pretty_string = json_encode($dane_uzytkownika_php, JSON_PRETTY_PRINT);
echo "<h3>Z JSON_PRETTY_PRINT:</h3>";
echo "<pre>" . htmlspecialchars($json_pretty_string) . "</pre>";
/* Wynik:
{
"id": 101,
"imie": "Anna",
"email": "anna.nowak@example.com",
"tagi": [
"php",
"webdev",
"kurs"
]
}
*/
// Przykład 3: Polskie znaki i JSON_UNESCAPED_UNICODE
$dane_polskie = [
"miasto" => "Łódź",
"opis" => "Zażółć gęślą jaźń"
];
$json_polskie_escaped = json_encode($dane_polskie, JSON_PRETTY_PRINT);
echo "<h3>Polskie znaki (domyślnie escaped):</h3>";
echo "<pre>" . htmlspecialchars($json_polskie_escaped) . "</pre>";
/* Wynik:
{
"miasto": "\u0141\u00f3d\u017a",
"opis": "Za\u017c\u00f3\u0142\u0107 g\u0119\u015bl\u0105 ja\u017a\u0144"
}
*/
$json_polskie_unescaped = json_encode($dane_polskie, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
echo "<h3>Polskie znaki (z JSON_UNESCAPED_UNICODE):</h3>";
echo "<pre>" . htmlspecialchars($json_polskie_unescaped) . "</pre>";
/* Wynik:
{
"miasto": "Łódź",
"opis": "Zażółć gęślą jaźń"
}
*/
// Przykład 4: Kodowanie obiektu PHP
class Produkt {
public $nazwa;
public $cena;
private $id_wewnetrzne; // Prywatne właściwości nie są domyślnie kodowane
public function __construct($nazwa, $cena, $id_wewnetrzne) {
$this->nazwa = $nazwa;
$this->cena = $cena;
$this->id_wewnetrzne = $id_wewnetrzne;
}
}
$produkt_obj = new Produkt("Super Gadżet", 79.99, "XYZ123");
$json_obiekt = json_encode($produkt_obj, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
echo "<h3>Kodowanie obiektu PHP:</h3>";
echo "<pre>" . htmlspecialchars($json_obiekt) . "</pre>";
// Wynik (tylko publiczne właściwości):
// {
// "nazwa": "Super Gadżet",
// "cena": 79.99
// }
// Aby zakodować również prywatne/chronione właściwości, obiekt musi implementować interfejs JsonSerializable
// lub można użyć sztuczki z konwersją na tablicę (ale to nie zawsze idealne).
// Przykład 5: Obsługa błędów z JSON_THROW_ON_ERROR (PHP >= 7.3)
$niepoprawne_dane_utf8 = "\xB1\x31"; // Niepoprawny ciąg UTF-8
try {
$json_error = json_encode($niepoprawne_dane_utf8, JSON_THROW_ON_ERROR);
echo $json_error;
} catch (JsonException $e) {
echo "<h3>Błąd kodowania JSON (JsonException):</h3>";
echo "Wiadomość: " . $e->getMessage() . "<br>"; // Np. "Malformed UTF-8 characters, possibly incorrectly encoded"
echo "Kod: " . $e->getCode() . "<br>";
}
?>
Dekodowanie Danych JSON do PHP - Funkcja json_decode()
Funkcja json_decode() służy do konwersji stringa JSON na zmienną PHP (domyślnie obiekt typu stdClass, lub tablicę asocjacyjną, jeśli podano odpowiednią opcję).
Składnia: mixed json_decode(string $json, ?bool $associative = null, int $depth = 512, int $flags = 0)
$json: String JSON do zdekodowania. Musi być poprawnie zakodowany w UTF-8.$associative(opcjonalny): Wartość logiczna. Jeślitrue, obiekty JSON będą konwertowane na tablice asocjacyjne PHP. Jeślifalse(domyślnie) lubnull, będą konwertowane na obiektystdClass.$depth(opcjonalny): Maksymalna głębokość zagnieżdżenia struktury JSON do zdekodowania. Domyślnie 512.$flags(opcjonalny): Maska bitowa. Najważniejsze stałe:JSON_BIGINT_AS_STRING: Dekoduje duże liczby całkowite jako stringi zamiast liczb zmiennoprzecinkowych (co mogłoby prowadzić do utraty precyzji).JSON_OBJECT_AS_ARRAY: To samo co ustawienie$associativenatrue.JSON_THROW_ON_ERROR(od PHP 7.3.0): Rzuca wyjątekJsonExceptionw przypadku błędu dekodowania. Preferowany sposób obsługi błędów.
Funkcja zwraca zdekodowaną wartość PHP (obiekt, tablicę, string, liczbę, boolean lub null) w przypadku sukcesu, lub null w przypadku błędu (chyba że użyto JSON_THROW_ON_ERROR). Uwaga: null może być również poprawną wartością JSON, więc do sprawdzania błędów należy używać json_last_error() (lub wyjątków).
<?php
$json_data_string =
'{ "id": 205, "produkt": "Książka PHP", "cena": 99.50, "dostepny": true, "autor": { "imie": "Cezary", "nazwisko": "PHPowiec" }, "tagi": ["programowanie", "php", "web"] }';
// Przykład 1: Dekodowanie do obiektu stdClass (domyślnie)
$dane_php_obj = json_decode($json_data_string);
echo "<h3>Dekodowanie do obiektu stdClass:</h3>";
if ($dane_php_obj !== null) {
echo "ID Produktu: " . htmlspecialchars($dane_php_obj->id) . "<br>";
echo "Nazwa Produktu: " . htmlspecialchars($dane_php_obj->produkt) . "<br>";
echo "Cena: " . htmlspecialchars($dane_php_obj->cena) . "<br>";
echo "Dostępny: " . ($dane_php_obj->dostepny ? "Tak" : "Nie") . "<br>";
echo "Autor: " . htmlspecialchars($dane_php_obj->autor->imie) . " " . htmlspecialchars($dane_php_obj->autor->nazwisko) . "<br>";
echo "Tagi: " . htmlspecialchars(implode(", ", $dane_php_obj->tagi)) . "<br>";
} else {
echo "Błąd dekodowania JSON!<br>";
}
// Przykład 2: Dekodowanie do tablicy asocjacyjnej
$dane_php_array = json_decode($json_data_string, true); // lub $associative = true
echo "<h3>Dekodowanie do tablicy asocjacyjnej:</h3>";
if ($dane_php_array !== null) {
echo "ID Produktu: " . htmlspecialchars($dane_php_array["id"]) . "<br>";
echo "Nazwa Produktu: " . htmlspecialchars($dane_php_array["produkt"]) . "<br>";
echo "Cena: " . htmlspecialchars($dane_php_array["cena"]) . "<br>";
echo "Dostępny: " . ($dane_php_array["dostepny"] ? "Tak" : "Nie") . "<br>";
echo "Autor: " . htmlspecialchars($dane_php_array["autor"]["imie"]) . " " . htmlspecialchars($dane_php_array["autor"]["nazwisko"]) . "<br>";
echo "Tagi: " . htmlspecialchars(implode(", ", $dane_php_array["tagi"])) . "<br>";
} else {
echo "Błąd dekodowania JSON!<br>";
}
// Przykład 3: Obsługa błędów dekodowania (PHP >= 7.3 z JSON_THROW_ON_ERROR)
$niepoprawny_json_string = '{ "nazwa": "Test", "wiek: 30 }'; // Brak cudzysłowu przy kluczu wiek
try {
$wynik = json_decode($niepoprawny_json_string, false, 512, JSON_THROW_ON_ERROR);
// var_dump($wynik);
} catch (JsonException $e) {
echo "<h3>Błąd dekodowania JSON (JsonException):</h3>";
echo "Wiadomość: " . $e->getMessage() . "<br>"; // Np. "Syntax error"
echo "Kod: " . $e->getCode() . "<br>";
}
?>
Obsługa Błędów JSON (dla PHP < 7.3 lub bez JSON_THROW_ON_ERROR)
Jeśli nie używasz JSON_THROW_ON_ERROR, musisz ręcznie sprawdzać błędy po wywołaniu json_encode() lub json_decode(). Służą do tego funkcje:
json_last_error(): Zwraca kod ostatniego błędu, który wystąpił podczas ostatniego wywołania funkcji JSON. ZwracaJSON_ERROR_NONE(wartość 0), jeśli nie było błędu.json_last_error_msg()(od PHP 5.5.0): Zwraca czytelny dla człowieka komunikat o ostatnim błędzie.
Możliwe kody błędów (stałe JSON_ERROR_*):
JSON_ERROR_NONE: Brak błędu.JSON_ERROR_DEPTH: Osiągnięto maksymalną głębokość stosu.JSON_ERROR_STATE_MISMATCH: Nieprawidłowy lub źle sformatowany JSON (np. niedomknięte nawiasy).JSON_ERROR_CTRL_CHAR: Znaleziono nieoczekiwany znak kontrolny.JSON_ERROR_SYNTAX: Błąd składni.JSON_ERROR_UTF8: Niepoprawnie zakodowane znaki UTF-8, prawdopodobnie błąd kodowania.JSON_ERROR_RECURSION(od PHP 5.5.0): Wykryto rekurencję w wartości przekazanej dojson_encode().JSON_ERROR_INF_OR_NAN(od PHP 5.5.0): Wykryto wartośćINFlubNANw wartości przekazanej dojson_encode().JSON_ERROR_UNSUPPORTED_TYPE(od PHP 5.5.0): Przekazano nieobsługiwany typ danych dojson_encode()(np. zasób).- ... i inne, bardziej specyficzne błędy.
<?php
$bledny_json = "{ 'klucz': 'wartość' }"; // Użyto apostrofów zamiast cudzysłowów - błąd składni JSON
$dane = json_decode($bledny_json);
if ($dane === null && json_last_error() !== JSON_ERROR_NONE) {
echo "<h3>Wystąpił błąd podczas dekodowania JSON:</h3>";
echo "Kod błędu: " . json_last_error() . "<br>";
if (function_exists('json_last_error_msg')) { // json_last_error_msg() od PHP 5.5
echo "Komunikat błędu: " . json_last_error_msg() . "<br>";
}
// Dla $bledny_json powyżej, błędem będzie JSON_ERROR_SYNTAX
} elseif ($dane === null) {
echo "Zdekodowano poprawnie, ale wynikiem jest null.<br>";
} else {
echo "<h3>Dane zdekodowane pomyślnie (sposób tradycyjny):</h3>";
// var_dump($dane);
}
?>
Używanie JSON_THROW_ON_ERROR z blokami try-catch jest jednak znacznie czystszym i nowocześniejszym podejściem do obsługi błędów JSON w PHP 7.3+.
Praktyczne Zastosowania JSON w PHP
- Komunikacja z API Webowymi (REST API): Wiele API (np. pogodowe, mapowe, social media) zwraca dane w formacie JSON. PHP może łatwo pobrać te dane (np. za pomocą cURL lub funkcji
file_get_contents()z odpowiednimi ustawieniami strumienia) i zdekodować je za pomocąjson_decode(). - Wysyłanie Danych do API: Podobnie, jeśli API oczekuje danych w formacie JSON w ciele żądania (np. POST, PUT), PHP może zakodować tablicę lub obiekt do JSON za pomocą
json_encode()i wysłać. - Konfiguracja Aplikacji: Pliki konfiguracyjne mogą być przechowywane w formacie JSON ze względu na jego czytelność i łatwość parsowania.
- Przechowywanie Danych w Bazach Danych NoSQL: Wiele baz danych NoSQL (np. MongoDB) używa formatu BSON (binarny JSON) lub bezpośrednio JSON do przechowywania dokumentów. PHP może łatwo przygotować dane w tym formacie. Nawet relacyjne bazy danych (np. MySQL, PostgreSQL) oferują typy JSON do przechowywania struktur JSON w kolumnach.
- Wymiana Danych z JavaScript po Stronie Klienta (AJAX): JSON jest naturalnym formatem do wymiany danych między PHP (backend) a JavaScript (frontend) w żądaniach AJAX. PHP może generować JSON, który jest następnie łatwo przetwarzany przez JavaScript.
<?php
// Przykład: Pobieranie danych z prostego publicznego API (JSONPlaceholder)
$url_api = "https://jsonplaceholder.typicode.com/users/1";
// Użycie file_get_contents (dla prostych GET, wymaga allow_url_fopen=On w php.ini)
// W produkcji lepiej użyć cURL dla większej kontroli i obsługi błędów.
$json_response = @file_get_contents($url_api);
if ($json_response === false) {
echo "Nie udało się pobrać danych z API.<br>";
} else {
try {
$user_data = json_decode($json_response, true, 512, JSON_THROW_ON_ERROR);
echo "<h3>Dane użytkownika z API:</h3>";
echo "Imię: " . htmlspecialchars($user_data["name"]) . "<br>";
echo "Email: " . htmlspecialchars($user_data["email"]) . "<br>";
echo "Miasto: " . htmlspecialchars($user_data["address"]["city"]) . "<br>";
} catch (JsonException $e) {
echo "Błąd dekodowania odpowiedzi JSON z API: " . $e->getMessage() . "<br>";
}
}
// Przykład: Generowanie JSON dla odpowiedzi AJAX
// header('Content-Type: application/json; charset=utf-8'); // Ważny nagłówek!
$odpowiedz_ajax = [
"status" => "success",
"wiadomosc" => "Operacja zakończona pomyślnie!",
"dane" => ["id_rekordu" => 42, "nowa_wartosc" => "Zaktualizowano"]
];
// echo json_encode($odpowiedz_ajax, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR);
// exit;
?>
Bezpieczeństwo i Dobre Praktyki
- Walidacja Danych Wejściowych: Zawsze waliduj dane otrzymane w formacie JSON z zewnętrznych źródeł (np. od użytkownika, z API). Nie ufaj, że struktura i typy będą zgodne z oczekiwaniami. Sprawdzaj istnienie kluczy, typy wartości, zakresy itp.
- Oczyszczanie Danych Wyjściowych (Sanitization): Jeśli dane z JSON mają być wyświetlone w HTML, zawsze je oczyszczaj (np. za pomocą
htmlspecialchars()), aby zapobiec atakom XSS. - Używaj
JSON_THROW_ON_ERROR: W PHP 7.3+ jest to preferowany sposób obsługi błędów kodowania/dekodowania JSON, ponieważ pozwala na użycie standardowych mechanizmów wyjątków. - Ustawiaj Nagłówek
Content-Type: Gdy serwujesz JSON jako odpowiedź HTTP (np. dla AJAX lub API), ustawiaj poprawny nagłówek:header('Content-Type: application/json; charset=utf-8');. - Kodowanie UTF-8: Upewnij się, że wszystkie stringi przekazywane do
json_encode()są w kodowaniu UTF-8. Podobnie, string JSON przekazywany dojson_decode()powinien być w UTF-8. UżywajJSON_UNESCAPED_UNICODEdla lepszej czytelności JSON z polskimi znakami. - Głębokość Rekursji (
$depth): Bądź świadomy limitu głębokości przy kodowaniu i dekodowaniu, aby uniknąć błędówJSON_ERROR_DEPTHprzy bardzo zagnieżdżonych strukturach. - Prywatne Właściwości Obiektów: Pamiętaj, że
json_encode()domyślnie koduje tylko publiczne właściwości obiektów. Aby kontrolować serializację, obiekt może implementować interfejsJsonSerializablei jego metodęjsonSerialize().
Podsumowanie Lekcji
JSON jest niezwykle ważnym formatem wymiany danych we współczesnym programowaniu webowym. PHP dostarcza prostych, ale potężnych funkcji json_encode() i json_decode(), które umożliwiają efektywną pracę z tym formatem. Zrozumienie składni JSON, opcji dostępnych w funkcjach PHP oraz zasad bezpieczeństwa jest kluczowe dla każdego dewelopera PHP. Umiejętność kodowania tablic i obiektów PHP do JSON oraz dekodowania stringów JSON na struktury danych PHP otwiera drzwi do integracji z licznymi API i efektywnej komunikacji z aplikacjami klienckimi.
W następnej lekcji podsumujemy dotychczas zdobytą wiedzę z podstaw PHP, przygotowując się do bardziej zaawansowanych tematów.
Zadanie praktyczne
Stwórz skrypt PHP, który:
- Definiuje tablicę asocjacyjną PHP reprezentującą informacje o książce: tytuł, autor (jako kolejna tablica asocjacyjna z imieniem i nazwiskiem), rok wydania (liczba), ISBN (string) oraz listę tagów (tablica indeksowana stringów). Użyj polskich znaków w tytule i autorze.
- Koduje tę tablicę do formatu JSON, używając opcji
JSON_PRETTY_PRINTorazJSON_UNESCAPED_UNICODE. Wyświetl wynikowy string JSON (użyjhtmlspecialchars()do wyświetlenia w HTML). - Tworzy string JSON ręcznie (jako tekst), który zawiera błąd składniowy (np. brakujący przecinek lub cudzysłów).
- Próbuje zdekodować ten błędny string JSON używając
json_decode()z opcjąJSON_THROW_ON_ERRORw blokutry-catch. Wyświetl komunikat o błędzie, jeśli wystąpi. - Próbuje zdekodować poprawny string JSON (ten wygenerowany w punkcie 2) z powrotem na tablicę asocjacyjną PHP. Wyświetl tytuł i imię autora z odkodowanej tablicy.
Pokaż przykładowe rozwiązanie
<?php
// 1. Definicja tablicy PHP z informacjami o książce
$ksiazka_php = [
"tytul" => "Pan Tadeusz, czyli ostatni zajazd na Litwie",
"autor" => [
"imie" => "Adam",
"nazwisko" => "Mickiewicz"
],
"rokWydania" => 1834,
"isbn" => "978-83-7779-590-1",
"tagi" => ["epopeja narodowa", "romantyzm", "poemat", "lektura szkolna"]
];
echo "<h3>1. Dane książki w PHP:</h3>";
echo "<pre>";
print_r($ksiazka_php);
echo "</pre>";
// 2. Kodowanie do JSON z opcjami
$json_ksiazka = json_encode($ksiazka_php, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR);
echo "<h3>2. Zakodowany JSON:</h3>";
echo "<pre>" . htmlspecialchars($json_ksiazka) . "</pre>";
// 3. Błędny string JSON
$bledny_json_string = '{ "tytul": "Błędna Książka", "autor": "Nieznany" "rok": 2023 }'; // Brak przecinka po "Nieznany"
echo "<h3>4. Próba dekodowania błędnego JSON:</h3>";
try {
$zdekodowany_bledny = json_decode($bledny_json_string, true, 512, JSON_THROW_ON_ERROR);
echo "<p>Błędny JSON został (niespodziewanie) zdekodowany:</p>";
echo "<pre>";
print_r($zdekodowany_bledny);
echo "</pre>";
} catch (JsonException $e) {
echo "<p style='color:red;'>Wystąpił błąd podczas dekodowania błędnego JSON:<br>";
echo "Komunikat: " . htmlspecialchars($e->getMessage()) . "<br>";
echo "Kod: " . htmlspecialchars($e->getCode()) . "</p>";
}
// 5. Dekodowanie poprawnego JSON z powrotem do tablicy PHP
echo "<h3>5. Dekodowanie poprawnego JSON do tablicy PHP:</h3>";
try {
$ksiazka_zdekodowana_php = json_decode($json_ksiazka, true, 512, JSON_THROW_ON_ERROR);
echo "<p>Tytuł: " . htmlspecialchars($ksiazka_zdekodowana_php["tytul"]) . "</p>";
echo "<p>Autor: " . htmlspecialchars($ksiazka_zdekodowana_php["autor"]["imie"]) . " " . htmlspecialchars($ksiazka_zdekodowana_php["autor"]["nazwisko"]) . "</p>";
} catch (JsonException $e) {
echo "<p style='color:red;'>Wystąpił błąd podczas dekodowania poprawnego JSON:<br>";
echo "Komunikat: " . htmlspecialchars($e->getMessage()) . "<br>";
echo "Kod: " . htmlspecialchars($e->getCode()) . "</p>";
}
?>
Zadanie do samodzielnego wykonania
Napisz skrypt, który pobiera dane o losowym użytkowniku z publicznego API https://randomuser.me/api/. API to zwraca dane w formacie JSON.
- Użyj
file_get_contents()(lub cURL, jeśli wolisz) do pobrania danych z API. - Zdekoduj odpowiedź JSON do tablicy asocjacyjnej PHP. Pamiętaj o obsłudze błędów (zarówno pobierania, jak i dekodowania JSON).
- Wyświetl następujące informacje o użytkowniku: imię, nazwisko, płeć, adres email oraz pełny adres (ulica, miasto, kraj).
- Stwórz nową tablicę PHP zawierającą tylko wybrane przez Ciebie informacje (np. imię, nazwisko, email, zdjęcie-thumbnail). Zakoduj tę nową tablicę do formatu JSON z opcją
JSON_PRETTY_PRINTi wyświetl wynik.
FAQ - Praca z JSON w PHP
Czy JSON jest lepszy niż XML?
JSON jest często preferowany nad XML w kontekście API webowych ze względu na mniejszą rozwlekłość, prostszą składnię i lepsze dopasowanie do struktur danych w JavaScript. XML nadal ma swoje zastosowania, szczególnie w systemach korporacyjnych, dokumentach i tam, gdzie wymagane są schematy (XSD) czy transformacje (XSLT).
Jak obsłużyć bardzo duże pliki JSON w PHP?
json_decode() wczytuje cały string JSON do pamięci. Dla bardzo dużych plików JSON, które nie mieszczą się w pamięci, potrzebne są techniki strumieniowego parsowania. Można użyć bibliotek takich jak JSON Machine lub salsify/jsonstreamingparser, które pozwalają przetwarzać JSON fragment po fragmencie.
Co jeśli mój string JSON nie jest w UTF-8?
Funkcje JSON w PHP oczekują stringów w UTF-8. Jeśli masz dane w innym kodowaniu (np. ISO-8859-2, Windows-1250), musisz je najpierw przekonwertować na UTF-8, np. za pomocą funkcji mb_convert_encoding() lub iconv(), przed przekazaniem do json_encode() lub json_decode().
Czy mogę przechowywać komentarze w pliku JSON?
Standard JSON nie dopuszcza komentarzy. Jeśli potrzebujesz komentarzy w pliku konfiguracyjnym, rozważ użycie formatu JSONC (JSON with Comments) i odpowiedniego parsera, lub innego formatu jak YAML, który natywnie wspiera komentarze.
Jak przekształcić obiekt PHP na JSON, włączając prywatne właściwości?
Najlepszym sposobem jest zaimplementowanie interfejsu JsonSerializable w klasie obiektu. Metoda jsonSerialize() tej klasy musi zwrócić dane, które mają być zserializowane przez json_encode(). W tej metodzie masz pełną kontrolę nad tym, które właściwości (publiczne, prywatne, chronione) i w jakiej formie zostaną uwzględnione.
Czy json_decode(..., true) zawsze jest lepsze niż dekodowanie do obiektu?
To zależy od preferencji i kontekstu. Praca z tablicami asocjacyjnymi ($assoc = true) jest często bardziej naturalna dla programistów PHP przyzwyczajonych do tablic. Obiekty stdClass mogą być nieco bardziej wydajne w niektórych przypadkach i są bliższe oryginalnej koncepcji JSON jako notacji obiektowej. Wybór zależy od stylu kodowania i wymagań projektu.
Co oznacza opcja JSON_NUMERIC_CHECK w json_encode()?
Ta opcja próbuje automatycznie przekonwertować stringi zawierające liczby na typy numeryczne w wynikowym JSON. Należy jej używać ostrożnie, ponieważ może prowadzić do nieoczekiwanych rezultatów lub utraty danych, jeśli string nie jest poprawną liczbą lub reprezentuje np. numer telefonu z wiodącymi zerami, który nie powinien być traktowany jako liczba.