Najlepsze praktyki formatowania JSON
JSON (JavaScript Object Notation) stał się de facto standardem wymiany danych w sieci Web. API zwracają JSON, pliki konfiguracyjne używają JSON, a nawet bazy danych przechowują dokumenty JSON. Mimo swojej prostoty, JSON ma ścisłe reguły składniowe, które łatwo naruszyć, a nieprawidłowo sformatowany JSON prowadzi do trudności w debugowaniu, problemów z wydajnością i luk bezpieczeństwa. Ten przewodnik obejmuje wszystko, co musisz wiedzieć o prawidłowym formatowaniu JSON, od podstawowej składni po zaawansowane tematy, takie jak walidacja Schema i obsługa dużych plików.
Czym jest JSON?
JSON to lekki, tekstowy format wymiany danych wywodzący się ze składni literałów obiektowych JavaScript. Został określony przez Douglasa Crockforda na początku lat 2000 i standaryzowany jako ECMA-404 i RFC 8259. Cele projektowe JSON to prostota, czytelność dla człowieka i łatwość implementacji w różnych językach programowania. Dziś każdy główny język programowania zawiera wbudowane wsparcie dla JSON.
JSON obsługuje sześć typów danych: stringi (w cudzysłowach), liczby (całkowite i zmiennoprzecinkowe), wartości boolowskie (true i false), null, obiekty (nieuporządkowane kolekcje klucz-wartość) i tablice (uporządkowane listy). Nie obsługuje natywnie komentarzy, dat, danych binarnych ani wartości undefined.
Reguły składni JSON
JSON ma składnię, której należy ściśle przestrzegać. Nawet jeden błędny znak może spowodować niepowodzenie parsowania całego dokumentu. Zrozumienie tych zasad zapobiega najczęstszym błędom formatowania.
Ciągi muszą używać podwójnych cudzysłowów
Wszystkie wartości ciągów i klucze obiektów muszą być ujęte w podwójne cudzysłowy. Pojedyncze cudzysłowy nie są prawidłowymi separatorami ciągów JSON. Jest to jeden z najczęstszych błędów popełnianych przez deweloperów przechodzących z JavaScript, gdzie pojedyncze i podwójne cudzysłowy są wymienne.
// Invalid - single quotes
{'name': 'Alice', 'age': 30}
// Valid - double quotes
{"name": "Alice", "age": 30}Klucze obiektów muszą być w cudzysłowach
W przeciwieństwie do literałów obiektów JavaScript, JSON wymaga, aby wszystkie klucze obiektów były ujęte w podwójne cudzysłowy. Niezacytowane klucze są błędem składniowym.
// Invalid - unquoted keys
{name: "Alice", age: 30}
// Valid - quoted keys
{"name": "Alice", "age": 30}Zakaz końcowych przecinków
JSON nie zezwala na przecinek po ostatnim elemencie obiektu lub tablicy. To kolejny częsty błąd programistów JavaScript, gdzie przecinek końcowy jest dozwolony (a w niektórych przewodnikach stylu nawet zalecany).
// Invalid - trailing comma
{
"name": "Alice",
"age": 30,
}
// Valid - no trailing comma
{
"name": "Alice",
"age": 30
}Komentarze nieobsługiwane
JSON nie obsługuje komentarzy. // komentarze jednoliniowe i /* */ komentarze wieloliniowe są nieprawidłowe w JSON. Jeśli potrzebujesz dołączyć dokumentację, rozważ użycie osobnego pliku dokumentacji lub formatu JSONC (JSON z komentarzami) obsługiwanego przez niektóre narzędzia.
Ścisłe typy wartości
Wartości JSON muszą być jednym z sześciu obsługiwanych typów. undefined, NaN, Infinity i -Infinity nie są prawidłowymi wartościami JSON. Zawarcie którejkolwiek z nich spowoduje błąd parsowania lub wygeneruje niestandardowy JSON, który wiele parserów odrzuci.
Typowe błędy formatowania
Oprócz błędów składniowych istnieje kilka błędów formatowania, które tworzą technicznie poprawny, ale problematyczny JSON:
- Niespójne wcięcia: Mieszanie tabulatorów i spacji lub używanie różnych głębokości wcięć utrudnia czytanie JSON w przeglądach kodu i porównaniach diff. Standaryzuj na 2-spacjowych wcięciach, co jest najczęstszą konwencją.
- Głęboko zagnieżdżone struktury: JSON z więcej niż 4-5 poziomami zagnieżdżenia staje się trudny do czytania i debugowania. Rozważ spłaszczenie struktury lub podzielenie jej na osobne dokumenty.
- Niespójna kolejność kluczy: Choć obiekty JSON są technicznie nieuporządkowane, utrzymywanie spójnej kolejności kluczy (np. alfabetycznej lub według ważności) sprawia, że porównania diff są bardziej znacznące i zmniejsza konflikty scalania w kontroli wersji.
- Zbyt długie linie: tablice z wieloma elementami w jednej linii są trudne do przeglądania. Podziel długie tablice na wiele linii, po jednym elemencie na linię, dla lepszej czytelności.
- Brakująca lub niespójna obsługa null: zdecyduj, czy całkowicie pomijać wartości null, czy jawnie je uwzględniać, i stosuj tę decyzję konsekwentnie w całym API.
Pretty-print a kompresja
Dwa główne tryby formatowania JSON służą różnym celom i ważne jest, aby używać właściwego formatu w odpowiednim kontekście.
JSON sformatowany
Formatowanie dodaje wcięcia i znaki nowej linii, aby JSON był czytelny dla człowieka. Jest to niezbędne podczas rozwoju, debugowania i pisania dokumentacji. Większość formaterów JSON domyślnie używa wcięcia 2 spacji:
{
"users": [
{
"id": 1,
"name": "Alice",
"email": "alice@example.com"
},
{
"id": 2,
"name": "Bob",
"email": "bob@example.com"
}
]
}JSON skompresowany
Kompresja usuwa wszystkie niepotrzebne białe znaki, tworząc najmniejszy możliwy prawidłowy JSON. Jest to kluczowe dla produkcyjnych API, gdzie każdy bajt ma znaczenie:
{"users":[{"id":1,"name":"Alice","email":"alice@example.com"},{"id":2,"name":"Bob","email":"bob@example.com"}]}Kiedy używać którego
| Kontekst | Format | Przyczyna |
|---|---|---|
| Rozwój i debugowanie | Pretty-print | Czytelność i szybkie skanowanie |
| Pliki konfiguracyjne | Pretty-print | Ludzie muszą czytać i edytować te pliki |
| Odpowiedzi produkcyjnego API | Kompresuj | Mniejsze ładunki, szybsza transmisja |
| Pliki dziennika | Kompresja (jeden obiekt na linię) | Kompaktowe przechowywanie, łatwe do przeszukiwania grep |
| Kontrola wersji | Pretty-print | Znaczące różnice i mniej konfliktów scalania |
Walidacja JSON Schema
Chociaż walidacja składni JSON sprawdza, czy dokument jest poprawnie sformatowany, nie weryfikuje, czy dane mają oczekiwaną strukturę, typy lub wartości. JSON Schema wypełnia tę lukę, dostarczając słownictwo do opisywania oczekiwanego kształtu danych JSON.
Czym jest JSON Schema?
JSON Schema to dokument JSON opisujący strukturę innych dokumentów JSON. Pozwala określać wymagane pola, oczekiwane typy, zakresy wartości, wzorce stringów i struktury zagnieżdżonych obiektów. Dokument JSON zgodny ze Schema nazywany jest prawidłową instancją.
Typowe funkcje schematu
- Sprawdzanie typu: zapewnia, że pola są ciągami znaków, liczbami, wartościami logicznymi, obiektami lub tablicami.
- Pola wymagane: określa, które właściwości muszą być obecne.
- Walidacja ciągów: wymuszanie wzorców (wyrażenia regularne), minimalna/maksymalna długość i formaty (email, data-godzina, URI).
- Walidacja liczb: ustawianie wartości minimalnych, maksymalnych, granic wyłącznych i ograniczeń wielokrotności.
- Walidacja tablic: kontrolowanie typów elementów, minimalnej/maksymalnej liczby elementów i unikalności.
- Kompozycja: używanie allOf, anyOf, oneOf i not do złożonej logiki walidacji.
Kiedy używać walidacji schematu
Powinieneś używać walidacji JSON Schema za każdym razem, gdy otrzymujesz JSON z zewnętrznych źródeł: treści żądań API, pliki konfiguracyjne, importy danych i ładunki kolejek wiadomości. Walidacja schematu wyłapuje błędy wcześnie, dostarcza jasne komunikaty o błędach i służy jako żywa dokumentacja formatu danych. Biblioteki takie jak Ajv (JavaScript), jsonschema (Python) i json-schema-validator (Java) ułatwiają integrację walidacji schematu z dowolną aplikacją.
Wpływ rozmiaru JSON na wydajność
Rozmiar dokumentu JSON bezpośrednio wpływa na wydajność aplikacji w wielu aspektach: czas transmisji sieciowej, czas parsowania i zużycie pamięci. Zrozumienie tych wpływów pomaga podejmować świadome decyzje dotyczące formatowania i struktury JSON.
Transmisja sieciowa
Każdy bajt JSON musi być przesłany przez sieć z serwera do klienta. Na szybkich połączeniach różnica między 10KB a 100KB może wydawać się nieznaczna, ale dla użytkowników w sieciach komórkowych lub regionach o wolniejszym Internecie wpływ jest znaczący. Badania pokazują, że każde dodatkowe 100ms czasu ładowania zmniejsza współczynnik konwersji o około 1%. Kompresja zazwyczaj zmniejsza rozmiar JSON o 30-50%, a kompresja gzip dodatkowo o 70-85%. Zawsze włączaj kompresję gzip lub Brotli dla odpowiedzi JSON API.
Wydajność parsowania
Koszt parsowania JSON jest zaskakująco wysoki. W przypadku dużych dokumentów (powyżej 1MB) parsowanie na urządzeniach mobilnych może zająć setki milisekund. Koszt jest w przybliżeniu liniowy względem rozmiaru dokumentu. Kluczowe strategie redukcji kosztów parsowania obejmują: wysyłanie tylko danych potrzebnych klientowi (filtrowanie pól), stronicowanie dużych zestawów wyników oraz używanie bardziej wydajnych formatów serializacji, takich jak Protocol Buffers lub MessagePack, do komunikacji między usługami wewnętrznymi, gdzie czytelność dla człowieka nie jest potrzebna.
Zużycie pamięci
Sparsowany JSON zazwyczaj zużywa 3-10 razy więcej pamięci niż jego forma zserializowana, ponieważ każda wartość staje się oddzielnym obiektem z własną alokacją pamięci. Ciąg JSON o rozmiarze 1MB może używać 5-10MB RAM po sparsowaniu. Dla aplikacji JavaScript działających w przeglądarkach z ograniczoną pamięcią może to prowadzić do degradacji wydajności lub awarii na urządzeniach z niższej półki.
JSON a JSONL
JSON Lines (JSONL lub NDJSON) to pokrewny format, który rozwiązuje kluczowe ograniczenie JSON: wymóg parsowania całego dokumentu jako pojedynczej jednostki. W JSONL każda linia pliku jest kompletnym, niezależnym obiektem JSON.
Kiedy używać JSONL
- Pliki dziennika: każdy wpis dziennika jest samodzielnym obiektem JSON w osobnej linii. Możesz dołączać nowe rekordy bez modyfikowania istniejących danych i odczytywać dowolną linię niezależnie.
- Strumienie danych: przetwarzanie rekordów w miarę ich napływania, bez czekania na kompletny zestaw danych. Każda linia jest kompletną wiadomością.
- Duże zbiory danych: parsowanie i przetwarzanie rekordów pojedynczo, bez ładowania całego pliku do pamięci. Jest to kluczowe dla zbiorów danych przekraczających dostępną pamięć RAM.
- Przetwarzanie równoległe: dzielenie plików JSONL na granicach linii i dystrybucja fragmentów do różnych wątków roboczych. Jest to niemożliwe w przypadku standardowego JSON, ponieważ podział w dowolnej pozycji bajtowej zniszczyłby strukturę.
Kiedy trzymać się standardowego JSON
- Odpowiedzi API: Standardowy JSON jest oczekiwanym formatem REST API. Opakowywanie wyników w tablicę lub obiekt jest konwencjonalną i oczekiwaną praktyką.
- Pliki konfiguracyjne: konfiguracja jest zwykle ładowana jednorazowo, więc zalety strumieniowania JSONL są nieistotne.
- Zagnieżdżone struktury danych: jeśli Twoje dane mają złożone zagnieżdżenia, których nie można łatwo spłaszczyć do oddzielnych rekordów, standardowy JSON jest bardziej naturalny.
Obsługa dużych plików JSON
Duże pliki JSON (powyżej 10MB) stanowią unikalne wyzwania wymagające specjalnego traktowania. Standardowe metody parsowania mogą zawodzić lub działać słabo przy tej skali.
Parsery strumieniowe
Parsery strumieniowe (lub w stylu SAX) przetwarzają JSON przyrostowo, bez ładowania całego dokumentu do pamięci. Emitują zdarzenia, gdy napotykają elementy strukturalne, takie jak początek obiektu, pary klucz-wartość i elementy tablicy. To podejście używa stałej pamięci niezależnie od rozmiaru pliku. Biblioteki takie jak oboe.js (JavaScript), ijson (Python) i Jackson Streaming API (Java) zapewniają strumieniowe parsowanie JSON.
Praktyczne wskazówki dla dużych plików
- Najpierw konwertuj na JSONL: jeśli masz dużą tablicę JSON, konwersja na JSONL (jeden obiekt na linię) umożliwia przetwarzanie linia po linii za pomocą standardowych narzędzi, takich jak grep, awk i jq.
- Używaj narzędzi wiersza poleceń: jq to standardowe narzędzie do przetwarzania JSON z wiersza poleceń. Może wydajnie obsługiwać duże pliki i obsługuje tryb strumieniowy dla bardzo dużych danych wejściowych.
- Dzielenie i równoległość: podziel duże pliki JSONL na mniejsze fragmenty i przetwarzaj równolegle. Każdy fragment może być przetwarzany niezależnie, ponieważ każda linia jest samodzielna.
- Unikaj ładowania do pamięci: nigdy nie używaj JSON.parse() na plikach większych niż dostępna pamięć. Używaj parsera strumieniowego lub przetwarzaj plik linia po linii.
- Kompresja przechowywania: duże pliki JSON kompresują się bardzo dobrze za pomocą gzip (zazwyczaj redukcja 80-90%). Przechowuj skompresowane kopie do przechowywania i dekompresuj na bieżąco podczas przetwarzania.
Zagadnienia bezpieczeństwa JSON
Chociaż JSON jest formatem danych i sam w sobie nie jest niebezpieczny, sposób, w jaki aplikacje przetwarzają JSON, może wprowadzać luki. Zrozumienie tych zagrożeń jest niezbędne do budowania bezpiecznych systemów.
Nigdy nie używaj eval() do parsowania JSON
Najważniejsza zasada bezpieczeństwa: nigdy nie używaj funkcji eval() JavaScript do parsowania JSON. eval() wykonuje dowolny kod JavaScript, co oznacza, że złośliwy ładunek JSON może uruchomić kod na komputerze użytkownika. Zawsze używaj JSON.parse(), który parsuje tylko prawidłowy JSON i odrzuca wszelki kod wykonywalny. To nie podlega dyskusji.
JSONP i ryzyko cross-origin
JSONP (JSON z paddingiem) to technika omijania ograniczeń polityki samego pochodzenia, zanim CORS został szeroko wsparty. Działa poprzez opakowanie danych JSON w wywołanie funkcji, które jest wykonywane jako skrypt. Jest to z natury niebezpieczne, ponieważ wykonuje dowolny JavaScript z serwera strony trzeciej. Jeśli kontrolujesz zarówno klienta, jak i serwer, użyj CORS zamiast JSONP. JSONP powinien być uważany za technologię przestarzałą i należy go unikać w nowych aplikacjach.
Zanieczyszczenie prototypu
Podczas scalania lub głębokiego kopiowania obiektów JSON w JavaScript, uważaj na klucze takie jak __proto__, constructor i prototype. Jeśli JSON dostarczony przez użytkownika jest rekurencyjnie scalany z istniejącymi obiektami bez oczyszczania tych kluczy, może zmodyfikować prototyp wszystkich obiektów w aplikacji, prowadząc do eskalacji uprawnień lub odmowy usługi. Zawsze oczyszczaj klucze obiektów przed scalaniem.
Odmowa usługi przez głębokie zagnieżdżenie
Starannie spreparowane dokumenty JSON o ekstremalnej głębokości zagnieżdżenia (tysiące poziomów) mogą powodować błędy przepełnienia stosu w parserach rekurencyjnych. Złagodź to, ustawiając maksymalną głębokość zagnieżdżenia w parserze. Większość produkcyjnych parserów JSON pozwala skonfigurować to ograniczenie.
Walidacja danych wejściowych
Nigdy nie ufaj danym JSON z zewnętrznych źródeł. Zawsze waliduj strukturę, typy i zakresy wartości przychodzącego JSON przed użyciem. Walidacja JSON Schema jest najbardziej niezawodną metodą, ale nawet proste sprawdzenia wymaganych pól i asercji typów zapewniają znaczącą ochronę przed zniekształconymi lub złośliwymi danymi wejściowymi.
Potrzebujesz sformatować, zweryfikować lub skompresować JSON? Wypróbuj nasze darmowe narzędzia JSON online. Całe przetwarzanie odbywa się w twojej przeglądarce, zapewniając maksymalną szybkość i prywatność.
Narzędzia do formatowania JSONWalidator JSONFAQ
Jaka jest różnica między sformatowanym a skompresowanym JSON?
Sformatowany JSON zawiera białe znaki (wcięcia, znaki nowej linii) do czytania przez człowieka, podczas gdy skompresowany JSON usuwa wszystkie niepotrzebne białe znaki, aby zminimalizować rozmiar pliku. Używaj sformatowanego JSON podczas rozwoju i debugowania, a skompresowanego JSON w środowisku produkcyjnym dla mniejszych ładunków sieciowych i szybszego parsowania.
Jakie są najczęstsze błędy formatowania JSON?
Najczęstsze błędy to: końcowe przecinki po ostatnim elemencie obiektu lub tablicy, używanie pojedynczych cudzysłowów zamiast podwójnych dla ciągów, dodawanie komentarzy (JSON nie obsługuje komentarzy), używanie niezacytowanych kluczy obiektów oraz zawieranie wartości, które nie są prawidłowym JSON, takich jak undefined lub NaN.
Kiedy powinienem używać JSONL zamiast JSON?
Używaj JSONL (JSON Lines), gdy potrzebujesz przyrostowo przetwarzać rekordy, na przykład w przypadku plików dziennika, strumieni danych lub dużych zbiorów danych, które nie mieszczą się w pamięci. Każda linia jest kompletnym obiektem JSON, więc możesz czytać i parsować po jednej linii bez ładowania całego pliku. Standardowy JSON wymaga sparsowania całego dokumentu przed dostępem do jakichkolwiek danych.
Jak walidować JSON według schematu?
Użyj JSON Schema do zdefiniowania oczekiwanej struktury danych JSON, a następnie użyj bibliotek takich jak Ajv (JavaScript), jsonschema (Python) lub walidatora online do walidacji instancji według tego schematu. JSON Schema pozwala określić wymagane pola, typy, zakresy wartości, wzorce ciągów i struktury zagnieżdżonych obiektów.
Czy JSON jest bezpieczny do wymiany danych?
JSON sam w sobie jest formatem danych, który nie jest ani bezpieczny, ani niebezpieczny. Jednak sposób, w jaki analizujesz i używasz JSON, może wprowadzać luki. Głównym ryzykiem jest używanie eval() do parsowania JSON (nigdy tego nie rób — zawsze używaj JSON.parse()). Ponadto uważaj na JSONP, który może omijać politykę samego pochodzenia. Zawsze waliduj i oczyszczaj dane JSON z niezaufanych źródeł przed użyciem.