O JSON pode começar com "["?

178

Pelo que posso ler no json.org , todas as strings JSON devem começar com {(chaves) e os [caracteres (colchetes) representam um elemento da matriz no JSON.

Eu uso a json4jbiblioteca e recebi uma entrada que começa com [, então não achei que isso fosse JSON válido. Examinei brevemente o esquema JSON, mas não consegui encontrá-lo, afirmando que um arquivo JSON não pode ser iniciado [ou apenas pode ser iniciado {.

Tiberiu
fonte
(Aparentemente, existem várias bibliotecas JSON mal projetadas que exigem que você conheça o tipo JSON mais externo. A "correção" mais simples aqui é cercar a cadeia JSON [], analisá-la como uma matriz e usar o primeiro elemento da matriz.)
Hot Licks
Aparentemente, é mais seguro começar com {e não [para que não seja uma matriz Javascript válida e não possa ser usada para ataques de CSRF.
David Klempfner

Respostas:


218

JSON pode ser uma matriz ou um objeto. Especificamente fora do json.org:

JSON é construído em duas estruturas:

  • Uma coleção de pares nome / valor. Em vários idiomas, isso é realizado como um objeto, registro, estrutura, dicionário, tabela de hash, lista de chaves ou matriz associativa.
  • Uma lista ordenada de valores. Na maioria dos idiomas, isso é realizado como uma
    matriz, vetor, lista ou sequência.

Em seguida, descreve as duas estruturas como: Um objeto JSON Uma matriz JSON

Observe que os caracteres inicial e final são colchetes e colchetes, respectivamente.

Editar
E a partir daqui: http://www.ietf.org/rfc/rfc4627.txt

Um texto JSON é uma sequência de tokens. O conjunto de tokens inclui seis caracteres estruturais, cadeias, números e três nomes literais.

Um texto JSON é um objeto ou matriz serializada.

Atualização (2014)

Em março de 2014, existe um novo JSON RFC ( 7159 ) que modifica ligeiramente a definição (consulte as páginas 4/5).

A definição de acordo com a RFC 4627 foi: JSON-text = object / array

Isso foi alterado no RFC 7159 para: JSON-text = ws value ws

Onde wsrepresenta espaço em branco e valueé definido da seguinte maneira:

Um valor JSON DEVE ser um objeto, matriz, número ou string ou um dos três nomes literais a seguir:

false null true

Portanto, a resposta para a pergunta ainda é sim, o texto JSON pode começar com um colchete (ou seja, uma matriz). Mas, além de objetos e matrizes, agora também pode ser um número, sequência ou valores false, nullou true.

Além disso, isso foi alterado em relação à minha citação anterior do RFC 4627 (ênfase adicionada):

Um texto JSON é uma sequência de tokens. O conjunto de tokens inclui seis caracteres estruturais, cadeias, números e três nomes literais.

Um texto JSON é um valor serializado . Observe que certas especificações anteriores do JSON restringiam um texto JSON a ser um objeto ou uma matriz. As implementações que geram apenas objetos ou matrizes nas quais um texto JSON é solicitado serão interoperáveis ​​no sentido de que todas as implementações os aceitarão como textos JSON em conformidade.


obrigado, eu olho para esse número muitas vezes, aparentemente há um problema com a biblioteca json4j, que não gosta de um json com [.
Tiberiu

1
@ Tibério Hajas: Demorei um pouco para entender quando o encontrei. Mas depois de ver alguns exemplos de JSON e compará-los, eu realmente gosto de como eles fizeram isso. Em relação ao json4j, talvez você possa enviar um relatório de erro ao criador da biblioteca json4j .
Richard Marskell - Drackir

Provavelmente estou atrasado para a festa. Mas o que descobri na RFC 8259 diz que um texto JSON é uma sequência de tokens formados a partir de pontos de código Unicode que estão em conformidade com a gramática de valor JSON. O conjunto de tokens inclui seis tokens estruturais, cadeias, números e três tokens de nome literal. Parece que algo assim é legítimo: {"1234"}, {true}. No entanto, o que isso representa? Isto não é uma matriz, porque não há <code> [] </code>, nem este é um objeto, porque existem dois deles.
Nicholas Humphrey
1
@NicholasHumphrey O que escrevi acima ainda se aplica ao 8259. Na mesma seção 2 (gramática JSON), o texto JSON (também conhecido como documento JSON) é definido como: JSON-text = ws value wsonde "Um valor JSON DEVE ser um objeto, matriz, número ou string, ou um dos três nomes literais a seguir: falso, nulo, verdadeiro "de acordo com a Seção 3 (Valores). Seu exemplo não satisfaz essas restrições e, portanto, não é um JSON válido.
Richard Marskell - Drackir

Respostas:

8

Se a string que você está analisando começa com uma chave esquerda ([), você pode usar JSONArray.parsepara recuperar um objeto JSONArray e então usar get(i)onde i é um índice de 0 a JSONArray retornado 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();
      }
   }
}

Que produziu saída como:

{"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"}

Nota: se você tentar ligar JSONObject.parse(books.toString());, receberá o erro que encontrou:

java.io.IOException: Expecting '{' on line 1, column 2 instead, obtained token: 'Token: ['
Nathaniel Mills
fonte
1
Código mais simples pode usar instanceof JSONArray contra instanceof JSONObject no objeto retornado da chamada get para determinar qual classe deve ser utilizado para analisar o objeto ...
Nathaniel Mills
5

O WEBSITE JSON.ORG DIZ ....

https://www.json.org/

O site afirma claramente o seguinte:

JSON é construído em duas estruturas:

  1. Uma coleção de pares nome / valor. Em vários idiomas, isso é realizado como um objeto, registro, estrutura, dicionário, tabela de hash, lista de chaves ou matriz associativa.

  2. Uma lista ordenada de valores. Na maioria dos idiomas, isso é realizado como uma matriz, vetor, lista ou sequência.

Essas são estruturas de dados universais. Praticamente todas as linguagens de programação modernas as suportam de uma forma ou de outra. Faz sentido que um formato de dados intercambiável com linguagens de programação também seja baseado nessas estruturas. No JSON, eles assumem as seguintes formas:

OBJETO:

Um objeto é um conjunto não ordenado de pares nome / valor. Um objeto começa com {(colchete esquerdo) e termina com} (colchete direito). Cada nome é seguido por: (dois pontos) e os pares nome / valor são separados por (vírgula).

{string: value, string: value}

ARRAY:

Uma matriz é uma coleção ordenada de valores. Uma matriz começa com [(colchete esquerdo) e termina com] (colchete direito). Os valores são separados por (vírgula).

[value, value, value ….]

VALOR:

Um valor pode ser uma cadeia de caracteres entre aspas duplas, ou um número, verdadeiro ou falso ou nulo, ou um objeto ou uma matriz. Essas estruturas podem ser aninhadas.

CORDA:

Uma sequência é uma sequência de zero ou mais caracteres Unicode, entre aspas duplas, usando escapes de barra invertida. Um caractere é representado como uma única sequência de caracteres. Uma string é muito parecida com uma string C ou Java.

NÚMERO:

Um número é muito parecido com um número C ou Java, exceto que os formatos octal e hexadecimal não são usados.

SOBRE ESPAÇO:

Espaço em branco pode ser inserido entre qualquer par de tokens. Exceto alguns detalhes de codificação, que descrevem completamente o idioma.

J. Moreno
fonte
Bom com os exemplos; isso me ajudou a terminar de escrever meu teste de unidade para um validador JSON. Eu não tinha certeza do que se entende por string (por exemplo, deve ser uma string entre aspas duplas).
gimlichael
Entendo como isso pode ser confundido, a frase poderia ter sido um pouco mais concisa, começando da seguinte forma: "Uma sequência de zero ou mais caracteres Unicode ...". Expliquei de uma maneira que facilitou a visualização de alguns dos principais pontos. Embora seja uma resposta tardia, espero que acrescente alguma clareza, se necessário.
J. Moreno