web-dev-qa-db-fra.com

Pouvez-vous utiliser une virgule de fin dans un objet JSON?

Lorsque vous générez manuellement un objet ou un tableau JSON, il est souvent plus facile de laisser une virgule de fin sur le dernier élément de l'objet ou du tableau. Par exemple, le code à afficher à partir d'un tableau de chaînes pourrait ressembler (dans un C++, à un pseudocode):

s.append("[");
for (i = 0; i < 5; ++i) {
    s.appendF("\"%d\",", i);
}
s.append("]");

vous donnant une ficelle comme

[0,1,2,3,4,5,]

Est-ce permis?

342
Ben Combee

Malheureusement, la spécification JSON n'autorise pas les virgules de fin. Quelques navigateurs le permettent, mais vous devez généralement vous soucier de tous les navigateurs.

En général, j'essaie de résoudre le problème et d'ajouter la virgule avant la valeur réelle. Vous obtenez donc un code qui ressemble à ceci:

s.append("[");
for (i = 0; i < 5; ++i) {
  if (i) s.append(","); // add the comma only if this isn't the first entry
  s.appendF("\"%d\"", i);
}
s.append("]");

Cette ligne de code supplémentaire dans votre boucle for n'est guère chère ...

Une autre alternative que j’ai utilisée lors de la sortie d’une structure au format JSON à partir d’un dictionnaire de quelque forme que ce soit est de toujours ajouter une virgule après chaque entrée (comme vous le faites ci-dessus), puis d’ajouter une c'est juste paresseux; ->).

Ne fonctionne pas bien avec un tableau, malheureusement.

208
brianb

Non. La spécification JSON, telle que gérée par http://json.org , n'autorise pas les virgules. D'après ce que j'ai vu, certains analyseurs peuvent l'autoriser en silence lors de la lecture d'une chaîne JSON, tandis que d'autres génèrent des erreurs. Pour l'interopérabilité, vous ne devriez pas l'inclure.

Le code ci-dessus pourrait être restructuré, soit pour supprimer la virgule de fin lors de l'ajout du terminateur de tableau, soit pour ajouter la virgule avant les éléments, en ignorant celle du premier.

123
Ben Combee

Simple, bon marché, facile à lire et fonctionne toujours quelles que soient les spécifications.

$delimiter = '';
for ....  {
    print $delimiter.$whatever
    $delimiter = ',';
}

L'affectation redondante à $ delim est un très petit prix à payer . fonctionne aussi bien s'il n'y a pas de boucle explicite mais des fragments de code séparés.

98
Overflowee

Les virgules de fin sont autorisés en JavaScript, mais ne fonctionnent pas dans IE. Les spécifications JSON sans version de Douglas Crockford ne les autorisaient pas, et comme elles étaient sans version, cela n'était pas censé changer. La spécification JSON de l’ES5 les autorisait comme extension, mais la RFC 4627 de Crockford ne l’a pas laissée, et l’ES5 est revenue à leur interdiction. Firefox a emboîté le pas. Internet Explorer est la raison pour laquelle nous ne pouvons pas avoir de belles choses.

19
Tobu

Les codeurs PHP peuvent vouloir vérifier implode (). Cela prend un tableau rejoint en utilisant une chaîne.

De la docs ...

$array = array('lastname', 'email', 'phone');
echo implode(",", $array); // lastname,email,phone
12
Rik Heywood

Comme cela a déjà été dit, les spécifications JSON (basées sur ECMAScript 3) n'autorisent pas les virgules de fin. ES> = 5 le permet, vous pouvez donc utiliser cette notation en JS pur. On en a discuté et certains parseurs l'ont soutenu ( http://bolinfest.com/essays/json.html , http://whereswalden.com/2010/09/08/ spidermonkey-json-change-trailing-virgules-plus-acceptés- ), mais c’est le fait spécifique (comme indiqué sur http://json.org/ ) qu’il ne devrait pas travailler en JSON. Cette chose a dit ...

... Je me demande pourquoi personne n’a fait remarquer que vous pouvez diviser la boucle à la 0e itération et utiliser la virgule lead au lieu de la terminer pour vous débarrasser de l’odeur du code de comparaison et de toute surcharge de performances réelle dans le fichier boucle, ce qui donne un code plus court, plus simple et plus rapide (en l’absence de branchement/conditionnel dans la boucle) que les autres solutions proposées.

Par exemple. (dans un pseudocode de style C similaire au code proposé par OP):

s.append("[");
// MAX == 5 here. if it's constant, you can inline it below and get rid of the comparison
if ( MAX > 0 ) {
    s.appendF("\"%d\"", 0); // 0-th iteration
    for( int i = 1; i < MAX; ++i ) {
        s.appendF(",\"%d\"", i); // i-th iteration
    }
}
s.append("]");
12
vaxquis

Il est intéressant de noter que C et C++ (et je pense que C #, mais je ne suis pas sûr) permettent spécifiquement la virgule de fin, pour la raison invoquée: cela facilite beaucoup la génération par programme de listes. Vous ne savez pas pourquoi JavaScript n'a pas suivi leur exemple. 

6
James Curran

Utilisez JSON5. N'utilisez pas JSON. 

  • Les objets et les tableaux peuvent avoir des virgules
  • Les clés d'objet peuvent être non cotées si elles sont des identifiants valides
  • Les chaînes peuvent être entre guillemets simples
  • Les chaînes peuvent être divisées sur plusieurs lignes
  • Les nombres peuvent être hexadécimaux (base 16)
  • Les nombres peuvent commencer ou se terminer par un point décimal (premier ou dernier).
  • Les nombres peuvent inclure l'infini et l'infini.
  • Les nombres peuvent commencer par un signe plus (+) explicite.
  • Les commentaires en ligne (sur une seule ligne) et les commentaires sur les blocs (sur plusieurs lignes) sont autorisés.

http://json5.org/

https://github.com/aseemk/json5

4
user619271

Selon la spécification Classe JSONArray :

  • Un extra (virgule) peut apparaître juste avant le crochet de fermeture. 
  • La valeur NULL sera insérée quand il y aura une élision (virgule).

Donc, si je comprends bien, il devrait être autorisé à écrire:

[0,1,2,3,4,5,]

Mais il est possible que certains analyseurs syntaxiques renvoient le nombre 7 en tant que nombre d'éléments (comme IE8, comme l'a souligné Daniel Earwicker) au lieu du nombre attendu de 6.


Édité:

J'ai trouvé ce Validateur JSON qui valide une chaîne JSON contre RFC4627 (type de média application/json pour JavaScript Object Notation) et contre la spécification du langage JavaScript. En réalité, un tableau avec une virgule est considéré comme valide uniquement pour JavaScript et non pour la spécification RFC 4627.

Cependant, dans la spécification RFC 4627, il est indiqué que:

2.3. Tableaux

Une structure de tableau est représentée par des crochets entourant zéro ou plusieurs valeurs (ou éléments). Les éléments sont séparés par des virgules.

array = begin-array [ value *( value-separator value ) ] end-array

Pour moi, c'est encore un problème d'interprétation. Si vous écrivez que Les éléments sont séparés par des virgules (sans rien dire sur les cas spéciaux, comme le dernier élément), cela pourrait être interprété dans les deux sens. 

P.S. La RFC 4627 n'est pas une norme (comme explicitement indiqué) et est déjà obsolète par la RFC 7159 (qui est une norme proposée) RFC 7159

2
Timoty Weis

Je garde un compte actuel et le compare à un compte total. Si le nombre actuel est inférieur au nombre total, j’affiche la virgule.

Peut ne pas fonctionner si vous n'avez pas le nombre total avant d'exécuter la génération JSON.

Là encore, si vous utilisez PHP 5.2.0 ou une version ultérieure, vous pouvez simplement formater votre réponse à l’aide de l’API JSON intégrée.

1
eddie

D'après mon expérience passée, j'ai constaté que différents navigateurs traitaient différemment les virgules de fin en JSON. 

Firefox et Chrome le traitent très bien. Mais IE (Toutes les versions) semble rompre. Je veux dire vraiment casser et arrêter de lire le reste du script. 

Gardant cela à l'esprit et le fait qu'il est toujours agréable d'écrire du code conforme, je suggère de consacrer un effort supplémentaire pour s'assurer qu'il n'y a pas de virgule. 

:) 

1
dnshio

Ce n'est pas recommandé, mais vous pouvez quand même faire quelque chose comme ça pour l'analyser.

jsonStr = '[0,1,2,3,4,5,]';
let data;
eval('data = ' + jsonStr);
console.log(data)

0
feibing

Il existe un moyen d'éviter une branche si dans la boucle. 

s.append("[ "); // there is a space after the left bracket
for (i = 0; i < 5; ++i) {
  s.appendF("\"%d\",", i); // always add comma
}
s.back() = ']'; // modify last comma (or the space) to right bracket
0
Zhang Boyang

Puisqu'une boucle for est utilisée pour parcourir un tableau, ou une structure de données itérable similaire, nous pouvons utiliser la longueur du tableau comme indiqué,

awk -v header="FirstName,LastName,DOB" '
  BEGIN {
    FS = ",";
    print("[");
    columns = split(header, column_names, ",");
  }
  { print("  {");
    for (i = 1; i < columns; i++) {
      printf("    \"%s\":\"%s\",\n", column_names[i], $(i));
    }
    printf("    \"%s\":\"%s\"\n", column_names[i], $(i));
    print("  }");
  }
  END { print("]"); } ' datafile.txt

Avec datafile.txt contenant,

 Angela,Baker,2010-05-23
 Betty,Crockett,1990-12-07
 David,Done,2003-10-31
0

Je boucle habituellement sur le tableau et attache une virgule après chaque entrée de la chaîne. Après la boucle, je supprime à nouveau la dernière virgule.

Peut-être pas la meilleure façon, mais moins chère que de vérifier à chaque fois si c'est le dernier objet de la boucle, je suppose.

0
Nils

Avec Relaxed JSON, vous pouvez avoir des virgules de fin, ou simplement les laisser entre. Ils sont optionnels.

Il n'y a aucune raison que des virgules soient nécessaires pour analyser un document de type JSON.

Jetez un coup d'œil à la spécification JSON décontractée et vous verrez à quel point la spécification JSON d'origine est "bruyante". Beaucoup trop de virgules et de citations ...

http://www.relaxedjson.org

Vous pouvez également essayer votre exemple en utilisant cet analyseur RJSON en ligne et le voir correctement analysé.

http://www.relaxedjson.org/docs/converter.html?source=%5B0%2C1%2C2%2C3%2C4%2C5%2C%5D

0
Steven Spungin