Domanda

Quando si genera manualmente un oggetto o un array JSON, è spesso più semplice lasciare una virgola finale sull'ultimo elemento nell'oggetto o nell'array. Ad esempio, il codice per l'output da una matrice di stringhe potrebbe apparire (in uno pseudocodice come C ++):

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

dandoti una stringa come

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

È permesso?

È stato utile?

Soluzione

Purtroppo la specifica JSON non consente una virgola finale. Ci sono alcuni browser che lo permetteranno, ma generalmente devi preoccuparti di tutti i browser.

In generale, provo a risolvere il problema e aggiungo la virgola prima del valore effettivo, quindi si finisce con un codice simile al seguente:

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("]");

Quella riga aggiuntiva di codice nel tuo ciclo for non è quasi costosa ...

Un'altra alternativa che ho usato durante l'output di una struttura su JSON da un dizionario di qualche forma è quella di aggiungere sempre una virgola dopo ogni voce (come si sta facendo sopra) e quindi aggiungere una voce fittizia alla fine che non sia trascinata virgola (ma è semplicemente pigro; - >).

Sfortunatamente non funziona bene con un array.

Altri suggerimenti

No. Le specifiche JSON, come mantenute in http://json.org , non consentono le virgole finali. Da quello che ho visto, alcuni parser potrebbero permetterli silenziosamente durante la lettura di una stringa JSON, mentre altri genereranno errori. Per l'interoperabilità, non dovresti includerlo.

Il codice sopra potrebbe essere ristrutturato, sia per rimuovere la virgola finale quando si aggiunge il terminatore di matrice o per aggiungere la virgola prima degli elementi, saltando quella per la prima.

Semplice, economico, facile da leggere e funziona sempre indipendentemente dalle specifiche.

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

L'assegnazione ridondante a $ delim è un prezzo molto piccolo da pagare. Funziona altrettanto bene se non esiste un ciclo esplicito ma frammenti di codice separati.

Le virgole finali sono consentite in JavaScript, ma non funzionano in IE. Le specifiche JSON senza versione di Douglas Crockford non le consentivano, e poiché era senza versione questo non avrebbe dovuto cambiare. Le specifiche JSON ES5 le consentivano come estensione, ma RFC 4627 di Crockford non lo fece e ES5 tornò indietro per vietarli. Firefox ha seguito l'esempio. Internet Explorer è il motivo per cui non possiamo avere cose carine.

Come già detto, le specifiche JSON (basate su ECMAScript 3) non consentono la virgola finale. ES > = 5 lo consente, quindi puoi effettivamente utilizzare quella notazione in JS puro. È stato discusso e alcuni parser lo hanno supportato ( http: // bolinfest. com / essays / json.html , http://whereswalden.com/2010/09/08/spidermonkey-json-change-trailing-commas-no-longer-accepted/ ), ma è il fatto specifico (come mostrato in < a href = "http://json.org/" rel = "noreferrer"> http://json.org/ ) che non dovrebbe funzionare in JSON. Quella cosa ha detto ...

... Mi chiedo perché nessuno abbia sottolineato che puoi effettivamente dividere il ciclo alla 0a iterazione e usare la virgola iniziale invece di trascinarne una per eliminare l'odore del codice di confronto e qualsiasi sovraccarico di prestazioni effettive nel ciclo, risultante in un codice che è in realtà più breve, più semplice e più veloce (a causa di nessuna ramificazione / condizionali nel ciclo) rispetto ad altre soluzioni proposte.

es. (in uno pseudocodice di tipo C simile al codice proposto dall'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("]");

I programmatori PHP potrebbero voler controllare implode () . Questo prende un array che lo unisce usando una stringa.

Dai documenti ...

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

È interessante notare che sia C & amp; Il C ++ (e penso C #, ma non ne sono sicuro) consente specificamente la virgola finale - esattamente per il motivo indicato: Rende molto più semplice la generazione di elenchi a livello di programmazione. Non sono sicuro del motivo per cui JavaScript non ha seguito il loro esempio.

Usa JSON5. Non usare JSON.

  • Gli oggetti e le matrici possono avere virgole finali
  • Le chiavi degli oggetti possono essere non quotate se sono identificatori validi
  • Le stringhe possono essere a virgoletta singola
  • Le stringhe possono essere suddivise su più righe
  • I numeri possono essere esadecimali (base 16)
  • I numeri possono iniziare o terminare con un punto decimale (iniziale o finale).
  • I numeri possono includere Infinity e -Infinity.
  • I numeri possono iniziare con un segno più (+) esplicito.
  • Sono consentiti commenti sia in linea (a riga singola) che a blocchi (a più righe).

http://json5.org/

https://github.com/aseemk/json5

Secondo la Specifica della classe JSONArray :

  • Un extra, (virgola) potrebbe apparire poco prima della parentesi quadra di chiusura.
  • Il valore null verrà inserito quando c'è, (virgola) elision.

Quindi, a quanto ho capito, dovrebbe essere permesso di scrivere:

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

Ma potrebbe accadere che alcuni parser restituiscano il 7 come numero di oggetti (come IE8 come ha sottolineato Daniel Earwicker) invece del previsto 6.


A cura:

Ho trovato questo Validator JSON che convalida una stringa JSON rispetto a RFC 4627 (il tipo di supporto application / json per Notazione oggetto JavaScript) e rispetto alla specifica del linguaggio JavaScript. In realtà qui un array con una virgola finale è considerato valido solo per JavaScript e non per la specifica RFC 4627.

Tuttavia, nelle specifiche RFC 4627 si afferma che:

  

2.3. Array

     

Una struttura di array è rappresentata da parentesi quadre che circondano lo zero   o più valori (o elementi). Gli elementi sono separati da virgole.

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

Per me questo è di nuovo un problema di interpretazione. Se scrivi che Gli elementi sono separati da virgole (senza indicare qualcosa su casi speciali, come l'ultimo elemento), potrebbe essere compreso in entrambi i modi.

P.S. RFC 4627 non è uno standard (come esplicitamente dichiarato) ed è già obsoleto da RFC 7159 (che è uno standard proposto) RFC 7159

Dalla mia esperienza passata, ho scoperto che browser diversi gestiscono le virgole finali in JSON in modo diverso.

Sia Firefox che Chrome lo gestiscono bene. Ma IE (Tutte le versioni) sembra rompersi. Intendo davvero interrompere e smettere di leggere il resto della sceneggiatura.

Tenendo presente questo, e anche il fatto che è sempre bello scrivere codice conforme, ti suggerisco di spendere lo sforzo extra per assicurarti che non ci siano virgole finali.

:)

Conservo un conteggio corrente e lo confronto con un conteggio totale. Se il conteggio corrente è inferiore al conteggio totale, visualizzo la virgola.

Potrebbe non funzionare se non si dispone di un conteggio totale prima dell'esecuzione della generazione JSON.

Quindi, se stai usando PHP 5.2.0 o superiore, puoi semplicemente formattare la tua risposta usando l'API JSON integrata.

Con Relaxed JSON, puoi avere virgole finali, o semplicemente lasciare le virgole fuori . Sono opzionali.

Non è necessario che siano presenti virgole per analizzare un documento simile a JSON.

Dai un'occhiata alle specifiche JSON rilassate e vedrai quanto sono rumorose le specifiche JSON originali. Troppe virgole e virgolette ...

http://www.relaxedjson.org

Puoi anche provare il tuo esempio usando questo parser RJSON online e vederlo analizzare correttamente.

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

Di solito cerco sull'array e allego una virgola dopo ogni voce nella stringa. Dopo il ciclo, cancello di nuovo l'ultima virgola.

Forse non è il modo migliore, ma meno costoso di controllare ogni volta se è l'ultimo oggetto del ciclo, immagino.

Non è raccomandato, ma puoi comunque fare qualcosa del genere per analizzarlo.

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

Esiste un modo possibile per evitare un if-branch nel loop.

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

Poiché un ciclo for viene utilizzato per iterare su un array o una struttura di dati iterabile simile, possiamo usare la lunghezza dell'array come mostrato,

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

Con datafile.txt contenente,

 Angela,Baker,2010-05-23
 Betty,Crockett,1990-12-07
 David,Done,2003-10-31
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top