JSON peut-il commencer par «[»?


178

D'après ce que je peux lire sur json.org , toutes les chaînes JSON doivent commencer par {(accolades) et les [caractères (crochets) représentent un élément de tableau en JSON.

J'utilise la json4jbibliothèque et j'ai une entrée qui commence par [, donc je ne pensais pas que c'était du JSON valide. J'ai regardé brièvement le schéma JSON, mais je ne pouvais pas vraiment trouver qu'il indiquait qu'un fichier JSON ne peut pas commencer par [, ou qu'il ne peut que commencer par {.


(Il existe apparemment plusieurs bibliothèques JSON mal conçues qui nécessitent que vous connaissiez le type JSON le plus externe. La solution la plus simple consiste à entourer la chaîne JSON [], à l'analyser comme un tableau et à prendre le premier élément du tableau.)
Hot Licks

Apparemment, il est plus sûr de le faire commencer par {et non [afin que ce ne soit pas un tableau Javascript valide, et ne puisse pas être utilisé pour les attaques CSRF.
David Klempfner

Réponses:


218

JSON peut être un tableau ou un objet. Plus précisément hors de json.org:

JSON est construit sur deux structures:

  • Une collection de paires nom / valeur. Dans diverses langues, ceci est réalisé sous la forme d'un objet, enregistrement, struct, dictionnaire, table de hachage, liste à clé ou tableau associatif.
  • Une liste ordonnée de valeurs. Dans la plupart des langues, cela est réalisé sous forme de
    tableau, de vecteur, de liste ou de séquence.

Il décrit ensuite les deux structures comme suit: Un objet JSON Un tableau JSON

Notez que les caractères de début et de fin sont respectivement des accolades et des crochets.

Modifier
Et à partir d'ici: http://www.ietf.org/rfc/rfc4627.txt

Un texte JSON est une séquence de jetons. L'ensemble de jetons comprend six caractères structurels, des chaînes, des nombres et trois noms littéraux.

Un texte JSON est un objet ou un tableau sérialisé.

Mise à jour (2014)

Depuis mars 2014, il existe une nouvelle RFC JSON ( 7159 ) modifie légèrement la définition (voir pages 4/5).

La définition selon RFC 4627 était: JSON-text = object / array

Cela a été changé dans la RFC 7159 en: JSON-text = ws value ws

wsreprésente un espace et valueest défini comme suit:

Une valeur JSON DOIT être un objet, un tableau, un nombre ou une chaîne, ou l'un des trois noms littéraux suivants:

false null true

Donc, la réponse à la question est toujours oui, le texte JSON peut commencer par un crochet (c'est-à-dire un tableau). Mais en plus des objets et des tableaux, il peut maintenant aussi s'agir d'un nombre, d'une chaîne ou des valeurs false, nullou true.

En outre, cela a changé par rapport à ma précédente citation RFC 4627 (emphase ajoutée):

Un texte JSON est une séquence de jetons. L'ensemble de jetons comprend six caractères structurels, des chaînes, des nombres et trois noms littéraux.

Un texte JSON est une valeur sérialisée . Notez que certaines spécifications précédentes de JSON contraignaient un texte JSON à être un objet ou un tableau. Les implémentations qui génèrent uniquement des objets ou des tableaux pour lesquels un texte JSON est appelé seront interopérables dans le sens où toutes les implémentations les accepteront comme des textes JSON conformes.


merci, je regarde ce chiffre plusieurs fois, apparemment il y a un problème avec la bibliothèque json4j, qui n'aime pas un json avec [.
Tiberiu

1
@Tiberiu Hajas: Il m'a fallu un peu de temps pour le comprendre lorsque je l'ai trouvé pour la première fois. Mais après avoir vu quelques exemples de JSON et les avoir comparés, j'aime vraiment comment ils l'ont fait. En ce qui concerne json4j, peut - être vous pouvez soumettre un rapport de bogue à la bibliothèque de json4j créateur .
Richard Marskell - Drackir

Je suis probablement en retard pour la fête. Mais ce que j'ai trouvé dans la RFC 8259 dit qu'un texte JSON est une séquence de jetons formés à partir de points de code Unicode qui se conforme à la grammaire des valeurs JSON. L'ensemble de jetons comprend six jetons structurels, des chaînes, des nombres et trois jetons de nom littéraux. Cela ressemble à quelque chose comme ceci est légitime: {"1234"}, {true}. Mais qu'est-ce que cela représente? Ce n'est pas un tableau, car il n'y a pas de <code> [] </code>, ce n'est pas non plus un objet, car il y en a deux.
Nicholas Humphrey

1
@NicholasHumphrey Ce que j'ai écrit ci-dessus s'applique toujours en 8259. Dans cette même section 2 (Grammaire JSON), le texte JSON (alias un document JSON) est défini comme: JSON-text = ws value wsoù "Une valeur JSON DOIT être un objet, un tableau, un nombre ou une chaîne, ou l'un des trois noms littéraux suivants: faux, nul, vrai "selon la section 3 (valeurs). Votre exemple ne satisfait pas ces contraintes et n'est donc pas un JSON valide.
Richard Marskell - Drackir

8

Si la chaîne que vous analysez commence par une accolade gauche ([), vous pouvez utiliser JSONArray.parsepour récupérer un objet JSONArray, puis vous pouvez utiliser get(i)i est un index de 0 au JSONArray renvoyé 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();
      }
   }
}

Qui a produit une sortie comme:

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

Remarque: si vous tentez d'appeler, JSONObject.parse(books.toString());vous obtiendrez l'erreur que vous avez rencontrée:

java.io.IOException: Expecting '{' on line 1, column 2 instead, obtained token: 'Token: ['

1
Un code plus simple pourrait utiliser l'instance de JSONArray par rapport à l'instance de JSONObject sur l'objet renvoyé par l'appel get pour déterminer quelle classe doit être utilisée pour analyser l'objet ...
Nathaniel Mills

5

LE SITE WEB JSON.ORG DIT ...

https://www.json.org/

Le site indique clairement ce qui suit:

JSON est construit sur deux structures:

  1. Une collection de paires nom / valeur. Dans diverses langues, ceci est réalisé sous la forme d'un objet, enregistrement, struct, dictionnaire, table de hachage, liste à clé ou tableau associatif.

  2. Une liste ordonnée de valeurs. Dans la plupart des langues, cela est réalisé sous forme de tableau, de vecteur, de liste ou de séquence.

Ce sont des structures de données universelles. Pratiquement tous les langages de programmation modernes les prennent en charge sous une forme ou une autre. Il est logique qu'un format de données interchangeable avec les langages de programmation soit également basé sur ces structures. En JSON, ils prennent ces formes:

OBJET:

Un objet est un ensemble non ordonné de paires nom / valeur. Un objet commence par {(accolade gauche) et se termine par} (accolade droite). Chaque nom est suivi de: (deux-points) et les paires nom / valeur sont séparées par (virgule).

{string: value, string: value}

TABLEAU:

Un tableau est une collection ordonnée de valeurs. Un tableau commence par [(crochet gauche) et se termine par] (crochet droit). Les valeurs sont séparées par (virgule).

[value, value, value ….]

VALEUR:

Une valeur peut être une chaîne entre guillemets, ou un nombre, ou vrai ou faux ou nul, ou un objet ou un tableau. Ces structures peuvent être imbriquées.

CHAÎNE:

Une chaîne est une séquence de zéro ou plusieurs caractères Unicode, entourés de guillemets doubles, utilisant des échappements de barre oblique inverse. Un caractère est représenté sous la forme d'une chaîne de caractères unique. Une chaîne ressemble beaucoup à une chaîne C ou Java.

NOMBRE:

Un nombre ressemble beaucoup à un nombre C ou Java, sauf que les formats octal et hexadécimal ne sont pas utilisés.

À PROPOS DE WHITESPACE:

Des espaces blancs peuvent être insérés entre n'importe quelle paire de jetons. Sauf quelques détails d'encodage, cela décrit complètement la langue.


Bon avec les exemples; cela m'a aidé à finir d'écrire mon test unitaire pour un validateur JSON. Je n'étais pas sûr de ce que l'on entendait par chaîne (par exemple, il doit s'agir d'une chaîne entre guillemets doubles).
gimlichael

Je vois comment cela pourrait être confus, la phrase aurait pu être un peu plus concise commençant comme suit: "Une séquence de zéro ou plusieurs caractères Unicode ..." Je crois que l'auteur l'a peut-être ajouté pour accentuer. Je l'ai présenté de manière à ce qu'il soit plus facile de voir certains des points clés. Bien qu'une réponse tardive, j'espère que cela ajoute une certaine clarté si nécessaire.
J. Moreno
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.