Porównanie bibliotek do parsowania i przetwarzania JSON
Podsumowanie: Natywne API są najszybsze, parsery tolerujące błędy dają przesunięcia. Wybieraj według trzech rzeczy: lokalizacji błędu, zachowania oryginalnego tekstu i jawności granic.

Najważniejsze: najpierw zaklasyfikuj potrzebę, potem porównuj implementacje — używaj natywnego JSON.parse do wartości tylko do odczytu, jsonc-parser, gdy potrzebujesz przesunięć lub musisz zachować oryginalne formatowanie, a biblioteki zapytań i patchy dodawaj tylko tam, gdzie są wymagane; duże biblioteki ładuj leniwie per strona i usuwaj nieutrzymywane.
Każda biblioteka twierdzi, że jest „szybka, mała i kompletna”. Naprawdę różni je to, ile informacji potrafią dać, gdy coś pójdzie nie tak.
1. Cztery kategorie według celu
| Kategoria | Reprezentatywne biblioteki | Co rozwiązuje |
|---|---|---|
| Standardowe parsowanie | JSON.parse / JSON.stringify |
Składnia ↔ obiekt, szybkość przede wszystkim |
| Tolerancyjne parsowanie + edycja | jsonc-parser, json5 |
Wejście z komentarzami, błędy precyzyjne do przesunięcia, modyfikacje zachowujące formatowanie |
| Zapytania | jsonpath-plus, jsonpath |
Wybieranie węzłów po wyrażeniu |
| Modyfikacja | fast-json-patch, immer |
Generowanie i stosowanie patchy, aktualizacje niezmienne |
Najpierw rozpoznaj, w której kategorii jesteś, a potem porównuj konkretne implementacje — inaczej łatwo użyć biblioteki zapytań do pracy parsera.
2. Porównanie obok siebie
| Biblioteka | Lokalizacja błędu | Tolerancja (komentarze/przecinki końcowe) | Zachowuje oryginalne formatowanie | Pasujące scenariusze |
|---|---|---|---|---|
JSON.parse |
Tylko komunikat i position (zależne od silnika) | ✗ | ✗ | Domyślne parsowanie, dane API |
jsonc-parser |
Precyzyjny offset + kod błędu |
✓ | ✓ (modify + applyEdits) |
Edytory, pliki konfiguracyjne |
json5 |
Informacje o wierszu i kolumnie | ✓ (bardziej łagodne) | ✗ | Odczyt konfiguracji JSON5 |
jsonlint |
Informacje o wierszu i kolumnie | ✗ | ✗ | Tylko referencyjnie, nie jest aktywnie utrzymywana |
jsonpath-plus |
Błędy składni wyrażenia | — | — | Odpytywanie po wyrażeniu |
fast-json-patch |
Błędy na poziomie operacji | — | — | Generowanie i stosowanie patchy |
lz-string |
— | — | — | Kompresja JSON do URL |
Komunikaty błędów JSON.parse różnią się znacznie między silnikami. V8 produkuje coś w rodzaju
Unexpected token } in JSON at position 42, ale to, czy position jest dokładne, zależy od wersji silnika;
jsonc-parser zwraca natomiast stabilne, strukturalne { error, offset, length }, co pasuje do znaczników edytora.
3. Cztery kluczowe punkty decyzyjne
3.1 Czy potrzebujesz przesunięć
Jeśli budujesz edytor i chcesz „kliknij błąd, aby przejść do odpowiedniego wiersza”, musisz mieć przesunięcie. Test jest prosty: jeśli twój komunikat błędu potrafi tylko wypisać „niepoprawny JSON”, użytkownicy będą musieli sami go szukać.
import { parse, printParseErrorCode } from 'jsonc-parser';
const errors: Array<{ error: number; offset: number; length: number }> = [];
parse(text, errors, { allowTrailingComma: true, disallowComments: false });
if (errors.length > 0) {
const firstError = errors[0];
console.error(`${printParseErrorCode(firstError.error)} at offset ${firstError.offset}`);
}
3.2 Czy musisz zachować oryginalny tekst
Tylko odczyt wartości → dowolny parser wystarczy. „Zmień jedno pole i zachowaj wszystko inne dokładnie tak, jak było” → musisz użyć API w stylu edycji, a nie „parsowanie → zmiana obiektu → serializacja”.
To drugie gubi: komentarze, kolejność kluczy (w niektórych implementacjach), styl wcięć, notację literałów liczbowych (1e3 staje się 1000) oraz formy ucieczki (\u4e2d staje się faktycznym znakiem).
3.3 Czy zachowania brzegowe są jawne
Przed wyborem biblioteki sprawdź w dokumentacji trzy rzeczy:
- Jak obsługiwane są zduplikowane klucze (zachowanie ostatniego / zgłoszenie błędu);
- Czy duże liczby całkowite tracą precyzję (większość bibliotek JS traci, bo wszystkie przechodzą przez
Number); - Obsługiwany zakres BOM, komentarzy i przecinków końcowych.
Jeśli nie ma dokumentacji, napisz małą próbkę i przetestuj sam. To jest bardziej niezawodne niż czytanie README.
3.4 Stan utrzymania
Ryzykiem biblioteki JSON nie są brakujące funkcje, ale długotrwałe zaniedbanie: nikt nie wypuści już poprawek bezpieczeństwa (zanieczyszczenie prototypu, ReDoS).
4. Porównanie z innymi językami
| Język | Biblioteka standardowa / główna | Kluczowa różnica |
|---|---|---|
| JavaScript | JSON.parse |
Wszystkie liczby są podwójnej precyzji |
| TypeScript | Jak powyżej + jsonc-parser / zod |
Typy istnieją tylko w czasie kompilacji |
| Go | encoding/json |
Domyślnie float64, użyj UseNumber(), aby zachować precyzję; json.RawMessage do odroczonego parsowania |
| Java | Jackson / Gson / Moshi | W Jacksonie uważaj na ryzyko włączenia domyślnego typowania |
| Python | json / orjson |
parse_float=Decimal zachowuje precyzję; orjson jest szybszy, ale nie obsługuje wszystkich typów |
| Rust | serde_json |
Deserializacja silnie typowana; funkcja arbitrary_precision zachowuje precyzję |
| C++ | simdjson / RapidJSON | simdjson celuje w przepustowość parsowania, RapidJSON jest bardziej ogólny |
Przy wymianie danych między językami najłatwiej potknąć się wciąż na precyzji liczb i formatach czasu; wybór biblioteki może je tylko złagodzić, nie wyeliminować.
5. Typowe zestawy
Wariant 1: witryna narzędziowa (strona przeglądarki)
Parsing and error location: jsonc-parser
Editor: CodeMirror 6 + @codemirror/lang-json
Query: jsonpath-plus
Patch: fast-json-patch
Share links: lz-string
Cechą wyróżniającą tego zestawu jest to, że wszystko działa lokalnie i żadne dane nie są wysyłane, co odpowiada oczekiwaniom prywatności witryny użytkowej.
Wariant 2: brama API po stronie serwera
Validation: Ajv (compile the schema once, reuse it)
Parsing: native JSON.parse (together with a body size limit)
Deferred parsing of large fields: keep the raw string, parse only when needed
Nie wprowadzaj bibliotek zapytań i patchy do warstwy bramy, aby implementować logikę biznesową — to zadanie warstwy biznesowej.
Wariant 3: CLI i skrypty
Pick fields: jq
Format conversion: yq / dasel
Interactive browsing: jless
Batch validation: ajv-cli
6. Rzeczywisty wpływ rozmiaru paczki i wydajności
jsonc-parserjest bardzo mały i nadaje się do głównej paczki;json5jest nieco większy niżjsonc-parser, bo obsługuje więcej składni;jsonpath-pluszawiera ewaluację wyrażeń i jest zauważalnie większy, więc powinien być ładowany leniwie per strona;fast-json-patchjest średni i potrzebny tylko wtedy, gdy masz funkcję porównywania.
Optymalizacja jest prosta: importuj dynamicznie per strona i nie umieszczaj ich w paczce pierwszego ekranu.
const { JSONPath } = await import('jsonpath-plus');
7. Lista kontrolna
- [ ] Wybieraj biblioteki według celu; nie używaj biblioteki zapytań do parsowania;
- [ ] Używaj
jsonc-parser, gdy potrzebujesz precyzyjnych lokalizacji błędów; - [ ] Używaj API w stylu edycji, gdy komentarze i formatowanie muszą zostać zachowane;
- [ ] Przetestuj w praktyce trzy zachowania brzegowe: zduplikowane klucze, duże liczby całkowite i BOM;
- [ ] Obserwuj stan utrzymania biblioteki i ostrzeżenia bezpieczeństwa;
- [ ] Dynamicznie importuj duże biblioteki na żądanie.
FAQ
Jak dobrać bibliotekę JSON do rozmiaru projektu?
Małe narzędzia, które tylko czytają dane API, mogą zostać przy natywnym JSON.parse. Projekty wymagające lokalizacji błędów na poziomie edytora lub zachowania oryginalnego formatowania powinny użyć jsonc-parser. Brama po stronie serwera potrzebuje tylko walidacji i parsowania, zostawiając biblioteki zapytań i patchy warstwie biznesowej, a skrypty CLI mogą używać bezpośrednio jq, yq i ajv-cli.
Dlaczego stan utrzymania ma większe znaczenie niż liczba funkcji?
Prawdziwym ryzykiem biblioteki JSON jest długotrwałe zaniedbanie, a nie brakujące funkcje: nikt nie wypuści poprawek bezpieczeństwa dla zanieczyszczenia prototypu czy ReDoS. Choćby lista funkcji była kompletna, zatrzymana biblioteka zostawia cię z łataniem jej samodzielnie. Traktuj utrzymanie i ostrzeżenia bezpieczeństwa jako twarde kryteria, zamiast porównywać tabele funkcji.
Czy użyć JSON.parse, aby zmienić jedno pole i zachować komentarze oraz wcięcia?
Nie. Parsowanie, zmiana obiektu i serializacja gubią komentarze, kolejność kluczy, styl wcięć, notację literałów liczbowych (1e3 staje się 1000) oraz formy ucieczki (\u4e2d staje się faktycznym znakiem). Zmiana jednego pola z zachowaniem reszty wymaga API w stylu edycji, takiego jak modify i applyEdits w jsonc-parser.