Ciała żądań JSON - wartości testowe
Ciała żądań JSON, które parsery i bazy czytają różnie. Nazwy pól to przykład, podmień je na pola swojego API. 12 wartości, każda z tym, co psuje, i z tym, co zamiast tego robi poprawna aplikacja.
Wpisuj je po jednej skrótem AltShiftN
w palecie albo weź wszystkie do skryptu poleceniem nkb emit json-payloads.
Puste ciało żądania
json-payloads/empty-body- 0 grafemów
- 0 punktów kodowych
- 0 bajtów
- 0 jednostek UTF-16
- Co psuje
- Puste ciało nie jest JSON-em. Większość parserów zgłasza błąd, a niektóre nie zwracają żadnej wartości, więc obsługa napisana pod jeden z tych przypadków odpowiada 500 zamiast 400.
- Co robi poprawna aplikacja
- 400 z komunikatem, że ciało jest puste.
Powtórzony klucz
json-payloads/duplicate-key
{"quantity":1,"quantity":100}
{"quantity":1,"quantity":100}
- 29 grafemów
- 29 punktów kodowych
- 29 bajtów
- 29 jednostek UTF-16
- Co psuje
- RFC 8259 nie określa, co znaczą powtórzone nazwy: większość parserów bierze ostatnią wartość, a kilka odrzuca ciało, więc dwie warstwy z różnymi parserami mogą widzieć różną ilość.
- Co robi poprawna aplikacja
- Odrzucone z 400 albo ta sama wartość w każdej warstwie, która czyta ciało.
Liczba całkowita powyżej 2^53
json-payloads/big-int-id
{"id":9007199254740993}
{"id":9007199254740993}
- 23 grafemy
- 23 punkty kodowe
- 23 bajty
- 23 jednostki UTF-16
- Co psuje
- Powyżej 2^53 liczba typu double nie mieści każdej liczby całkowitej: JavaScript i mapa w Go czytają 9007199254740993 jako 9007199254740992, a typ int64 ją zachowuje, więc identyfikator zmienia się między dwiema usługami.
- Co robi poprawna aplikacja
- Identyfikatory powyżej 2^53 - 1 wysyłane jako napisy albo odrzucane z komunikatem.
Jawny null
json-payloads/explicit-null
{"name":null}
{"name":null}
- 13 grafemów
- 13 punktów kodowych
- 13 bajtów
- 13 jednostek UTF-16
- Co psuje
- Model z typami czyta null i brak pola jako tę samą pustą wartość, więc częściowa aktualizacja nie odróżni prośby o wyczyszczenie nazwy od prośby, która jej nie rusza.
- Co robi poprawna aplikacja
- Null i brak pola obsłużone jako dwa różne żądania, tak jak opisuje je API.
Liczba wysłana jako napis
json-payloads/number-as-string
{"quantity":"5"}
{"quantity":"5"}
- 16 grafemów
- 16 punktów kodowych
- 16 bajtów
- 16 jednostek UTF-16
- Co psuje
- Jedne mechanizmy wiązania czytają napis 5 jako liczbę 5, a inne go odrzucają, więc to samo ciało przechodzi przez jedną usługę i zostaje odrzucone przez następną w łańcuchu.
- Co robi poprawna aplikacja
- Odrzucone z 400, które nazywa pole i jego typ, albo zamienione tak samo w każdej warstwie.
1001 zagnieżdżonych tablic
json-payloads/nesting-1001
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
2 002 punkty kodowe w całości, środek wycięty
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
- 2 002 grafemy
- 2 002 punkty kodowe
- 2 002 bajty
- 2 002 jednostki UTF-16
- Co psuje
- Każdy parser zatrzymuje się na własnej głębokości, od 64 poziomów do 1000 albo bez limitu, więc ciało, które jedna warstwa czyta, druga odrzuca błędem głębokości zamiast błędu składni.
- Co robi poprawna aplikacja
- Odrzucone z 400 na udokumentowanej głębokości, zanim zobaczy je jakakolwiek obsługa.
Escapowany samotny surogat
json-payloads/lone-surrogate
{"name":"\ud800"}
{"name":"\\ud800"}
- 17 grafemów
- 17 punktów kodowych
- 17 bajtów
- 17 jednostek UTF-16
- Co psuje
- Escapowany samotny surogat jest poprawną składnią JSON, ale nie poprawnym tekstem: część parserów go odrzuca, encoding/json w Go zamienia go na U+FFFD, a inne trzymają go do chwili, w której zapis w UTF-8 pada albo go zmienia.
- Co robi poprawna aplikacja
- Odrzucone z 400 albo widocznie zastąpione, zanim wartość zostanie zapisana.
Escapowany NUL w napisie
json-payloads/escaped-nul
{"name":"a\u0000b"}
{"name":"a\\u0000b"}
- 19 grafemów
- 19 punktów kodowych
- 19 bajtów
- 19 jednostek UTF-16
- Co psuje
- Parsery JSON zostawiają NUL w napisie, więc dociera on do bazy: jsonb w PostgreSQL go odrzuca, a kod oparty na napisach z C ucina nazwę po a.
- Co robi poprawna aplikacja
- Odrzucone z 400 na wejściu API albo NUL usunięty, zanim wartość zostanie zapisana.
Liczba poza zakresem double
json-payloads/huge-exponent
{"price":1e400}
{"price":1e400}
- 15 grafemów
- 15 punktów kodowych
- 15 bajtów
- 15 jednostek UTF-16
- Co psuje
- 1e400 to poprawny JSON i więcej, niż mieści double: Go i serde go odrzucają, Python, .NET i Jackson czytają nieskończoność, JavaScript zapisuje z powrotem null, a jsonb w PostgreSQL trzyma wszystkie 401 cyfr.
- Co robi poprawna aplikacja
- Odrzucone z 400 jako wartość spoza zakresu pola.
Klucze różniące się wielkością liter
json-payloads/case-variant-keys
{"quantity":1,"Quantity":100}
{"quantity":1,"Quantity":100}
- 29 grafemów
- 29 punktów kodowych
- 29 bajtów
- 29 jednostek UTF-16
- Co psuje
- Wiązanie bez rozróżniania wielkości liter, domyślne w ASP.NET Core i w encoding/json w Go, bierze drugi klucz, a wiązanie, które je rozróżnia, bierze pierwszy albo odrzuca nieznany, więc warstwy nie zgadzają się co do ilości.
- Co robi poprawna aplikacja
- Odrzucone z 400 albo jeden udokumentowany klucz w każdej warstwie.
Przecinek na końcu
json-payloads/trailing-comma
{"quantity":1,}
{"quantity":1,}
- 15 grafemów
- 15 punktów kodowych
- 15 bajtów
- 15 jednostek UTF-16
- Co psuje
- Literały obiektów w JavaScripcie i JSON5 dopuszczają przecinek na końcu, a JSON nie, więc ciało pisane ręcznie albo przez pobłażliwego klienta pada na ścisłym serwerze, z 400 albo z 500.
- Co robi poprawna aplikacja
- 400 z komunikatem, który wskazuje przecinek.
Znacznik kolejności bajtów przed ciałem
json-payloads/bom-before-body
{"quantity":1}
\uFEFF{"quantity":1}
- 1 znak o zerowej szerokości
- 15 grafemów
- 15 punktów kodowych
- 17 bajtów
- 15 jednostek UTF-16
- Co psuje
- RFC 8259 zabrania znacznika kolejności bajtów przed JSON-em i pozwala parserom go pominąć: Jackson i dekodery, które go zdejmują, przyjmują ciało, a Go, serde i PostgreSQL je odrzucają, więc to samo żądanie przechodzi przez jedną usługę i pada w drugiej.
- Co robi poprawna aplikacja
- Przyjęte z pominiętym znacznikiem albo odrzucone z 400, które go nazywa, nigdy 500.