Czy JSON może zaczynać się od „[”?

178

Z tego, co mogę przeczytać na json.org , wszystkie ciągi JSON powinny zaczynać się od {(nawias klamrowy), a [znaki (nawiasy kwadratowe) reprezentują element tablicy w formacie JSON.

Korzystam z json4jbiblioteki i otrzymałem dane wejściowe zaczynające się od [, więc nie sądziłem, że to poprawny JSON. Przejrzałem krótko schemat JSON, ale tak naprawdę nie mogłem znaleźć stwierdzenia, że ​​plik JSON nie może zaczynać się od [lub może zaczynać się tylko od {.

Tiberiu
źródło
(Najwyraźniej istnieje kilka źle zaprojektowanych bibliotek JSON, które wymagają znajomości najbardziej zewnętrznego typu JSON. Najprostszym rozwiązaniem jest otoczenie ciągu JSON [], przeanalizowanie go jako tablicę i pobranie pierwszego elementu tablicy).
Hot Licks
Najwyraźniej bezpieczniej jest zacząć od {a nie [, aby nie była to poprawna tablica JavaScript i nie można jej było używać do ataków CSRF.
David Klempfner,

Odpowiedzi:


218

JSON może być tablicą lub obiektem. W szczególności poza json.org:

JSON jest zbudowany na dwóch strukturach:

  • Zbiór par nazwa / wartość. W różnych językach jest to realizowane jako obiekt, rekord, struktura, słownik, tabela skrótów, lista z kluczami lub tablica asocjacyjna.
  • Uporządkowana lista wartości. W większości języków jest to realizowane jako
    tablica, wektor, lista lub sekwencja.

Następnie opisuje dwie struktury jako: Obiekt JSON Tablica JSON

Zwróć uwagę, że znaki początkowe i końcowe to odpowiednio nawiasy klamrowe i nawiasy kwadratowe.

Edytuj
I stąd: http://www.ietf.org/rfc/rfc4627.txt

Tekst JSON to sekwencja tokenów. Zestaw tokenów zawiera sześć znaków strukturalnych, ciągi, liczby i trzy nazwy literałów.

Tekst JSON to serializowany obiekt lub tablica.

Aktualizacja (2014)

Od marca 2014 r. Pojawił się nowy kod JSON RFC ( 7159 ), który nieznacznie modyfikuje definicję (patrz strony 4/5).

Definicja według RFC 4627 była następująca: JSON-text = object / array

Zostało to zmienione w RFC 7159 na: JSON-text = ws value ws

Gdzie wsreprezentuje białe znaki i valuejest zdefiniowane w następujący sposób:

Wartość JSON MUSI być obiektem, tablicą, liczbą lub ciągiem albo jedną z trzech następujących nazw literałów:

false null true

Tak więc odpowiedź na pytanie nadal brzmi tak, tekst JSON może zaczynać się od nawiasu kwadratowego (tj. Tablicy). Ale oprócz obiektów i tablic, może teraz być również liczba, ciąg znaków lub wartości false, nulllub true.

Ponadto zmieniło się to w porównaniu z moim poprzednim cytatem RFC 4627 (podkreślenie dodane):

Tekst JSON to sekwencja tokenów. Zestaw tokenów zawiera sześć znaków strukturalnych, ciągi, liczby i trzy nazwy literałów.

Tekst JSON to zserializowana wartość . Zwróć uwagę, że niektóre wcześniejsze specyfikacje formatu JSON ograniczały tekst JSON do bycia obiektem lub tablicą. Implementacje, które generują tylko obiekty lub tablice, w których wywoływany jest tekst JSON, będą interoperacyjne w tym sensie, że wszystkie implementacje zaakceptują je jako zgodne teksty JSON.


dzięki, patrzę na tę liczbę wiele razy, najwyraźniej jest problem z biblioteką json4j, która nie lubi json z [.
Tiberiu,

1
@Tiberiu Hajas: Zajęło mi trochę czasu, zanim to zrozumiałem, kiedy to znalazłem. Ale po obejrzeniu kilku przykładów JSON i porównaniu ich, naprawdę podoba mi się, jak to zrobili. Odnośnie json4j, być może można wysłać raport o błędzie do biblioteki json4j za twórcę .
Richard Marskell - Drackir

Pewnie spóźnię się na przyjęcie. Ale to, co znalazłem w RFC 8259, mówi, że tekst JSON to sekwencja tokenów utworzona z punktów kodowych Unicode, która jest zgodna z gramatyką wartości JSON. Zestaw tokenów zawiera sześć żetonów strukturalnych, ciągi znaków, liczby i trzy żetony nazw literalnych. Wygląda na to, że coś takiego jest uzasadnione: {"1234"}, {prawda}. Jednak co to oznacza? To nie jest tablica, ponieważ nie ma <code> [] </code>, ani nie jest to obiekt, ponieważ jest ich dwa.
Nicholas Humphrey
1
@NicholasHumphrey To, co napisałem powyżej, nadal obowiązuje w 8259. W tej samej sekcji 2 (Gramatyka JSON) tekst JSON (aka dokument JSON) jest zdefiniowany jako: JSON-text = ws value wsgdzie „Wartość JSON MUSI być obiektem, tablicą, liczbą lub ciągiem znaków, lub jedna z następujących trzech nazw literałów: false, null, true ”zgodnie z sekcją 3 (wartości). Twój przykład nie spełnia tych ograniczeń, więc nie jest prawidłowym formatem JSON.
Richard Marskell - Drackir

Odpowiedzi:

8

Jeśli ciąg, który analizujesz, zaczyna się od lewego nawiasu klamrowego ([), którego możesz użyć JSONArray.parsedo odzyskania obiektu JSONArray, a następnie możesz użyć, get(i)gdzie i jest indeksem od 0 do zwróconych JSONArray's size()-1.

import java.io.IOException;
import com.ibm.json.java.JSONArray;
import com.ibm.json.java.JSONObject;

public class BookListTest {
   public static void main(String[] args) {
      String jsonBookList = "{\"book_list\":{\"book\":[{\"title\":\"title 1\"},{\"title\":\"title 2\"}]}}";
      Object book_list;
      try {
         book_list = JSONObject.parse(jsonBookList);
         System.out.println(book_list);
         Object bookList = JSONObject.parse(book_list.toString()).get("book_list");
         System.out.println(bookList);
         Object books = JSONObject.parse(bookList.toString()).get("book");
         System.out.println(books);
         JSONArray bookArray = JSONArray.parse(books.toString());
         for (Object book : bookArray) {
            System.out.println(book);
         }
      } catch (IOException e) {
         e.printStackTrace();
      }
   }
}

Który dał wynik, taki jak:

{"book_list":{"book":[{"title":"title 1"},{"title":"title 2"}]}}
{"book":[{"title":"title 1"},{"title":"title 2"}]}
[{"title":"title 1"}, {"title":"title 2"}]
{"title":"title 1"}
{"title":"title 2"}

Uwaga: jeśli spróbujesz zadzwonić JSONObject.parse(books.toString());, otrzymasz napotkany błąd:

java.io.IOException: Expecting '{' on line 1, column 2 instead, obtained token: 'Token: ['
Nathaniel Mills
źródło
1
Bardziej prosty kod może używać instanceof JSONArray versus instanceof JSONObject na obiekcie zwróconym przez wywołanie get, aby określić, która klasa powinna zostać użyta do przeanalizowania obiektu ...
Nathaniel Mills
5

STRONA JSON.ORG MÓWI ...

https://www.json.org/

Witryna wyraźnie stwierdza, co następuje:

JSON jest zbudowany na dwóch strukturach:

  1. Zbiór par nazwa / wartość. W różnych językach jest to realizowane jako obiekt, rekord, struktura, słownik, tabela skrótów, lista z kluczami lub tablica asocjacyjna.

  2. Uporządkowana lista wartości. W większości języków jest to realizowane jako tablica, wektor, lista lub sekwencja.

To są uniwersalne struktury danych. Praktycznie wszystkie współczesne języki programowania obsługują je w takiej czy innej formie. Ma sens, aby format danych, który jest wymienny z językami programowania, również był oparty na tych strukturach. W JSON przyjmują następujące formy:

OBIEKT:

Obiekt to nieuporządkowany zestaw par nazwa / wartość. Obiekt zaczyna się od {(lewy nawias klamrowy) i kończy na} (prawy nawias). Po każdej nazwie następuje: (dwukropek), a pary nazwa / wartość są oddzielone (przecinek).

{string: value, string: value}

SZYK:

Tablica to uporządkowany zbiór wartości. Tablica zaczyna się od [(lewy nawias) i kończy na] (prawy nawias). Wartości są oddzielone (przecinek).

[value, value, value ….]

WARTOŚĆ:

Wartość może być łańcuchem w podwójnych cudzysłowach, liczbą, prawdą, fałszem lub null, obiektem lub tablicą. Struktury te mogą być zagnieżdżane.

STRUNOWY:

Łańcuch to sekwencja zera lub więcej znaków Unicode, umieszczona w podwójnych cudzysłowach, przy użyciu odwrotnych ukośników. Znak jest reprezentowany jako pojedynczy ciąg znaków. Ciąg jest bardzo podobny do ciągu w języku C lub Java.

NUMER:

Liczba jest bardzo podobna do liczby w języku C lub Java, z tym wyjątkiem, że nie są używane formaty ósemkowe i szesnastkowe.

O WHITESPACE:

Spacje można wstawić między dowolną parę tokenów. Z wyjątkiem kilku szczegółów dotyczących kodowania, które całkowicie opisują język.

J. Moreno
źródło
Dobrze z przykładami; pomogło mi to zakończyć pisanie testu jednostkowego dla walidatora JSON. Nie byłem pewien, co oznacza ciąg znaków (np. Musi to być ciąg umieszczony w podwójnych cudzysłowach).
gimlichael
Widzę, że można to pomylić, zdanie mogłoby być nieco bardziej zwięzłe, zaczynając od następującego sformułowania: „Sekwencja zera lub więcej znaków Unicode…”. Myślę, że autor mógł je dodać dla podkreślenia. Ułożyłem to w sposób, który ułatwił dostrzeżenie niektórych kluczowych punktów. Chociaż odpowiedź jest spóźniona, mam nadzieję, że w razie potrzeby doda to nieco jasności.
J. Moreno,