¿Puede JSON comenzar con "["?

178

Por lo que puedo leer en json.org , todas las cadenas JSON deben comenzar con {(llave), y los [caracteres (corchetes) representan un elemento de matriz en JSON.

Uso la json4jbiblioteca y recibí una entrada que comienza con [, así que no pensé que fuera JSON válido. Miré brevemente el esquema JSON, pero realmente no pude encontrar que indicaba que un archivo JSON no puede comenzar [, o que solo puede comenzar {.

Tiberiu
fuente
(Aparentemente, hay varias bibliotecas JSON mal diseñadas que requieren que conozca el tipo JSON más externo. La "solución" más simple aquí es rodear la cadena JSON [], analizarla como una matriz y tomar el primer elemento de la matriz).
Hot Licks
Aparentemente es más seguro que comience con {y no [para que no sea una matriz de Javascript válida y no pueda usarse para ataques CSRF.
David Klempfner

Respuestas:


218

JSON puede ser una matriz o un objeto. Específicamente fuera de json.org:

JSON se basa en dos estructuras:

  • Una colección de pares de nombre / valor. En varios idiomas, esto se realiza como un objeto, registro, estructura, diccionario, tabla hash, lista con clave o matriz asociativa.
  • Una lista ordenada de valores. En la mayoría de los idiomas, esto se realiza como una
    matriz, vector, lista o secuencia.

Luego continúa describiendo las dos estructuras como: Un objeto JSON Una matriz JSON

Tenga en cuenta que los caracteres iniciales y finales son llaves y corchetes respectivamente.

Editar
y desde aquí: http://www.ietf.org/rfc/rfc4627.txt

Un texto JSON es una secuencia de tokens. El conjunto de tokens incluye seis caracteres estructurales, cadenas, números y tres nombres literales.

Un texto JSON es un objeto o conjunto serializado.

Actualización (2014)

A partir de marzo de 2014, hay un nuevo JSON RFC ( 7159 ) que modifica ligeramente la definición (consulte las páginas 4/5).

La definición según RFC 4627 fue: JSON-text = object / array

Esto se ha cambiado en RFC 7159 a: JSON-text = ws value ws

Donde wsrepresenta el espacio en blanco y valuese define de la siguiente manera:

Un valor JSON DEBE ser un objeto, matriz, número o cadena, o uno de los siguientes tres nombres literales:

false null true

Entonces, la respuesta a la pregunta sigue siendo sí, el texto JSON puede comenzar con un corchete (es decir, una matriz). Pero además de los objetos y las matrices, ahora también puede ser un número, una cadena o los valores false, nullo true.

Además, esto ha cambiado desde mi cita anterior RFC 4627 (énfasis agregado):

Un texto JSON es una secuencia de tokens. El conjunto de tokens incluye seis caracteres estructurales, cadenas, números y tres nombres literales.

Un texto JSON es un valor serializado . Tenga en cuenta que ciertas especificaciones anteriores de JSON restringieron un texto JSON para ser un objeto o una matriz. Las implementaciones que generan solo objetos o matrices donde se requiere un texto JSON serán interoperables en el sentido de que todas las implementaciones aceptarán estos como textos JSON conformes.


gracias, miro esa cifra muchas veces, aparentemente hay un problema con la biblioteca json4j, que no le gusta un json con [.
Tiberiu

1
@Tiberiu Hajas: Me tomó un tiempo entenderlo cuando lo encontré por primera vez. Pero después de ver algunos ejemplos de JSON y compararlos, realmente me gusta cómo lo hicieron. Con respecto a json4j, tal vez pueda enviar un informe de error al creador de la biblioteca json4j .
Richard Marskell - Drackir

Probablemente llegue tarde a la fiesta. Pero lo que encontré en RFC 8259 dice que un texto JSON es una secuencia de tokens formados a partir de puntos de código Unicode que se ajustan a la gramática del valor JSON. El conjunto de tokens incluye seis tokens estructurales, cadenas, números y tres tokens de nombre literal. Parece que algo así es legítimo: {"1234"}, {true}. Sin embargo, ¿qué representa esto? Esto no es una matriz, porque no hay <code> [] </code>, tampoco es un objeto, porque hay dos de ellos.
Nicholas Humphrey
1
@NicholasHumphrey Lo que escribí anteriormente todavía se aplica en 8259. En esa misma sección 2 (Gramática JSON), el texto JSON (también conocido como documento JSON) se define como: JSON-text = ws value wsdonde "Un valor JSON DEBE ser un objeto, matriz, número o cadena, o uno de los siguientes tres nombres literales: falso, nulo, verdadero "según la Sección 3 (Valores). Su ejemplo no satisface esas restricciones y, por lo tanto, no es JSON válido.
Richard Marskell - Drackir

Respuestas:

8

Si la cadena que está analizando comienza con una llave izquierda ([), puede usarla JSONArray.parsepara recuperar un objeto JSONArray y luego puede usar get(i)donde i es un índice de 0 a través de los JSONArray devueltos 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 produjo resultados 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: si intentó llamar JSONObject.parse(books.toString());, obtendría el error que encontró:

java.io.IOException: Expecting '{' on line 1, column 2 instead, obtained token: 'Token: ['
Nathaniel Mills
fuente
1
Un código más simple podría usar instancia de JSONArray versus instancia de JSONObject en el objeto devuelto por la llamada get para determinar qué clase se debe usar para analizar el objeto ...
Nathaniel Mills
5

EL SITIO WEB JSON.ORG DICE ...

https://www.json.org/

El sitio establece claramente lo siguiente:

JSON se basa en dos estructuras:

  1. Una colección de pares de nombre / valor. En varios idiomas, esto se realiza como un objeto, registro, estructura, diccionario, tabla hash, lista con clave o matriz asociativa.

  2. Una lista ordenada de valores. En la mayoría de los idiomas, esto se realiza como una matriz, vector, lista o secuencia.

Estas son estructuras de datos universales. Prácticamente todos los lenguajes de programación modernos los admiten de una forma u otra. Tiene sentido que un formato de datos que sea intercambiable con lenguajes de programación también se base en estas estructuras. En JSON, toman estas formas:

OBJETO:

Un objeto es un conjunto desordenado de pares de nombre / valor. Un objeto comienza con {(llave izquierda) y termina con} (llave derecha). Cada nombre es seguido por: (dos puntos) y los pares de nombre / valor están separados por, (coma).

{string: value, string: value}

FORMACIÓN:

Una matriz es una colección ordenada de valores. Una matriz comienza con [(corchete izquierdo) y termina con] (corchete derecho). Los valores están separados por, (coma).

[value, value, value ….]

VALOR:

Un valor puede ser una cadena entre comillas dobles, o un número, o verdadero o falso o nulo, o un objeto o una matriz. Estas estructuras pueden estar anidadas.

CUERDA:

Una cadena es una secuencia de cero o más caracteres Unicode, entre comillas dobles, usando escapes de barra invertida. Un carácter se representa como una cadena de caracteres única. Una cadena es muy parecida a una cadena C o Java.

NÚMERO:

Un número es muy parecido a un número C o Java, excepto que los formatos octal y hexadecimal no se usan.

ACERCA DE WHITESPACE:

Se puede insertar un espacio en blanco entre cualquier par de tokens. Exceptuando algunos detalles de codificación, que describe completamente el idioma.

J. Moreno
fuente
Bien con los ejemplos; me ayudó a terminar de escribir mi prueba unitaria para un validador JSON. No estaba seguro de qué se entiende por cadena (por ejemplo, debe ser una cadena entre comillas dobles).
gimlichael
Veo cómo podría confundirse eso, la oración podría haber sido un poco más concisa comenzando de la siguiente manera: "Una secuencia de cero o más caracteres Unicode ..." Creo que el autor puede haberla agregado para enfatizar. Lo presenté de una manera que hizo más fácil ver algunos de los puntos clave. Aunque es una respuesta tardía, espero que agregue algo de claridad si es necesario.
J. Moreno