Você pode usar uma vírgula à direita em um objeto JSON?


392

Ao gerar manualmente um objeto ou matriz JSON, geralmente é mais fácil deixar uma vírgula à direita no último item do objeto ou matriz. Por exemplo, o código para saída de uma matriz de seqüências de caracteres pode parecer (em um C ++ como pseudocódigo):

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

dando-lhe uma corda como

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

Isso é permitido?


66
Era algo que eu precisava pesquisar na web há alguns dias atrás. Não vi uma resposta aqui no SO, portanto, ao seguir a missão do site, fiz a pergunta e respondi para que outros pudessem encontrá-la. Isso é algo que Jeff disse explicitamente que queria fazer aqui.
Ben Combee 14/10/08

5
Como Jeff disse, acho perfeitamente bom usar o SO como um 'caderno' de coisas que você passou algum tempo olhando para cima. Claro, isso é simples para esses tipos de itens, mas ainda acho apropriado, especialmente porque diferentes mecanismos javascript lidam com isso de maneira diferente.
pkaeding 14/10/08

6
Eu também estava pensando isso, por isso é uma pergunta perfeitamente razoável.
hoju 29/10/09

48
Para todos aqueles que reclamaram que alguém fez uma pergunta simples, por favor, recue. Esse foi um dos primeiros hits do google e me ajudou a fazer referência rápida à resposta. Obrigado OP.

40
Curiosamente (ou horripilante) no IE 8, acabei de descobrir que alert([1, 2, 3, ].length)exibirá "4".
precisa

Respostas:


250

Infelizmente, a especificação JSON não permite uma vírgula à direita. Existem alguns navegadores que permitirão, mas geralmente você precisa se preocupar com todos os navegadores.

Em geral, tento mudar o problema e adicionar vírgula antes do valor real, para que você acabe com um código parecido com este:

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

Essa linha de código extra no seu loop for dificilmente é cara ...

Outra alternativa que usei ao gerar uma estrutura para JSON a partir de um dicionário de alguma forma é sempre acrescentar uma vírgula após cada entrada (como você está fazendo acima) e depois adicionar uma entrada fictícia no final que não tem vírgula à direita (mas isso é apenas preguiçoso; ->).

Infelizmente, não funciona bem com uma matriz.


2
Comecei a usar essa formatação em todo o meu código JS (vírgula antes do item na mesma linha) exatamente por esse motivo. Torna vírgulas finais muito mais fáceis de localizar e economiza muito tempo. É irritante, eu gostaria que houvesse uma opção para lançar um erro para isso no firefox (já que isso ajudaria na depuração).
Rocketmonkeys

47
É realmente uma pena que o ECMA5 especifique rastreamentos, mas o JSON não.
FlavorScape

4
Sim, essa linha extra não custa caro, mas é um incômodo.
René Nyffenegger 30/10

2
Essa abordagem funciona para loops indexados. Que tal para ... em loops de estilo? Existe uma maneira elegante?
kgf3JfUtW

2
Essa linha de código extra pode ser complicada ao lidar com propriedades. Você pode ter toneladas de ifs apenas para evitar essa pequena vírgula estúpida. Sobre o custo YMMV, veja isso por exemplo jsfiddle.net/oriadam/mywL9384 Esclarecimento: Sua solução é ótima, eu odeio especificações que proíbem uma vírgula à direita.
oriadam 17/07/19

133

Não. A especificação JSON, mantida em http://json.org , não permite vírgulas finais. Pelo que vi, alguns analisadores podem silenciosamente permitir a leitura de uma string JSON, enquanto outros geram erros. Para interoperabilidade, você não deve incluí-lo.

O código acima pode ser reestruturado, para remover a vírgula à direita ao adicionar o terminador da matriz ou para adicionar a vírgula antes dos itens, ignorando o da primeira.


11
ECMA 262 Parece defini-lo na seção 11.1.5 - Inicializador de objetos. Se isso é bom ou não, parece estar na especificação.
Zero Distraction

6
Ser válido ECMAScript não significa necessariamente que um documento é válido JSON - JSON geralmente é definido no RFC 4627 , e essa especificação não permite a vírgula à direita.
Tim Gilbert

11
@ZeroDistraction: ECMA262 define ECMAscript (também conhecido como javascript), que é uma linguagem de programação como Perl ou Ruby ou C ++ ou Java. JSON é um formato de dados como XML ou CSV ou YAML. Eles não são a mesma coisa. O JSON não existe no EXMA262, mas a sintaxe da qual é derivado existe e é chamada de notação literal do objeto (ON no JSON).
Slebetman 16/05

106

Simples, barato, fácil de ler e sempre funciona, independentemente das especificações.

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

A atribuição redundante a $ delim é um preço muito pequeno a pagar. Também funciona tão bem se não houver loop explícito, mas fragmentos de código separados.


11
É o que normalmente faço em situações como essa; Sinto que a atribuição extra é mais do que compensada, eliminando o condicional necessário para acrescentar a vírgula antes do valor na abordagem alternativa ( stackoverflow.com/a/201856/8946 ).
Lawrence Dol

5
Não gosto dessa solução, pois há outra variável que polui meu escopo. Um ifé mais fácil de entender. Mas obrigado por compartilhar.
Ich

3
Além disso, é melhor conter o escopo do separador:for(let ..., sep=""; ... ; sep=",") { ...
Lawrence Dol

11
Eu gosto dessa abordagem porque evita condicionais, embora as CPUs modernas tenham uma boa lógica de previsão de ramificação. Consulte também Por que é mais rápido processar uma matriz classificada do que uma matriz não classificada?
Hossein

21

Vírgulas finais são permitidas em JavaScript, mas não funcionam no IE. A especificação JSON sem versão de Douglas Crockford não os permitia e, como era sem versão, isso não deveria mudar. A especificação JSON ES5 permitiu-os como uma extensão, mas o RFC 4627 de Crockford não, e o ES5 reverteu a proibi-los. O Firefox seguiu o exemplo. O Internet Explorer é o motivo pelo qual não podemos ter coisas agradáveis.


11
Eu apenas tentei no IE 11 sem nenhum problema. Em quais versões do IE você testou, onde as causou problemas?
Iconoclast

10
Parece que Crockford é o motivo pelo qual não podemos ter coisas boas. Isso e comentários em JSON
Hejazzman 19/17

Por que mencionar navegadores da Web quando o OP usou C ++ como pseudocódigo? É improvável que a pergunta do OP esteja relacionada a navegadores da Web ou JavaScript.
cowlinator

@cowlinator J ava S cript O bject N otation
forresthopkinsa

11
Javascript literais de objeto inspirou o formato, mas JSON não é para motores de JavaScript
cowlinator

13

Como já foi dito, a especificação JSON (baseada no ECMAScript 3) não permite vírgula à direita. ES> = 5 permite, para que você possa realmente usar essa notação em JS puro. Foi discutido e alguns analisadores o apoiaram ( http://bolinfest.com/essays/json.html , http://whereswalden.com/2010/09/08/spidermonkey-json-change-trailing-commas- não é mais aceito / ), mas é o fato das especificações (como mostrado em http://json.org/ ) que não deve funcionar no JSON. Aquilo disse ...

... Estou me perguntando por que ninguém apontou que você pode realmente dividir o loop na 0ª iteração e usar vírgula à esquerda, em vez de arrastar uma para se livrar do cheiro do código de comparação e de qualquer sobrecarga de desempenho real no loop, resultando em um código realmente mais curto, mais simples e mais rápido (devido a nenhuma ramificação / condicional no loop) do que outras soluções propostas.

Por exemplo (em um pseudocódigo no estilo C semelhante ao código proposto pelo 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("]");

3
Exemplo de código simples e rápido. Muito melhor do que soluções outras respostas propostas.
Trevor Jex

12

Os codificadores PHP podem querer verificar implode () . Isso leva uma matriz junta-lo usando uma seqüência de caracteres.

Dos documentos ...

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

2
Da mesma forma, o JavaScript possui join () . A maioria dos idiomas possui um método semelhante, ou um similar pode ser facilmente codificado.
Dan Burton

16
O PHP possui json_encode, que lida com todos os detalhes de criação de JSON, não apenas vírgulas.
Brilliand

Isso é legal! Como isso se aplica ao JSON e como ajuda o OP em uma resolução para sua pergunta? Lembre-se: "Você pode usar uma vírgula à direita em um objeto JSON?" é a questão.
Rockin4Life33 11/04

7

Curiosamente, tanto o C & C ++ (e acho que o C #, mas não tenho certeza) permitem especificamente a vírgula à direita - exatamente pelo motivo exposto: facilita muito a geração de listas por meio de programação. Não sei por que o JavaScript não seguiu sua liderança.


13
A ECMA especificou explicitamente que vírgulas à direita são permitidas na próxima especificação: ejohn.org/blog/bug-fixes-in-javascript-2 Mais um motivo para deixar claro que JSON! = JS Object.
Eyelidlessness 14/10/08

O PHP também permite. Eu acho que é a única característica do PHP que eu gosto. ; p
iconoclast

4

Use JSON5. Não use JSON.

  • Objetos e matrizes podem ter vírgulas à direita
  • As chaves de objeto podem não estar entre aspas se forem identificadores válidos
  • As strings podem ter aspas simples
  • As strings podem ser divididas em várias linhas
  • Os números podem ser hexadecimais (base 16)
  • Os números podem começar ou terminar com um ponto decimal (à esquerda ou à direita).
  • Os números podem incluir Infinito e-Infinito.
  • Os números podem começar com um sinal de mais explícito (+).
  • Comentários em linha (linha única) e em bloco (várias linhas) são permitidos.

http://json5.org/

https://github.com/aseemk/json5


Parece bom, mas não a adição de novos tipos de dados parece ser uma oportunidade perdida ... claro o desejo de permanecer um subconjunto estrito do ECMAScript 5 forças que, mas ainda assim ...
iconoclasta

11
Além disso, as cordas da mutlilina são terríveis. Eu sonho com as multilinhas ES6.
Marco Sulla

10
Não, esse é um conselho HORRÍVEL. De todas as bibliotecas JSON existentes, muito poucas suportam essa extensão; e tudo isso para "melhorias" muito questionáveis. NÃO cause mais erosão da interoperabilidade por novas extensões falsas como esta.
StaxMan

8
Acredito que gastar sua vida fixando vírgulas é mais horrível.
user619271

3

Existe uma maneira possível de evitar uma ramificação if no 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

2

De acordo com a especificação da classe JSONArray :

  • Um extra (vírgula) pode aparecer logo antes do colchete de fechamento.
  • O valor nulo será inserido quando houver, (vírgula) elisão.

Então, pelo que entendi, deve ser permitido escrever:

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

Mas pode acontecer que alguns analisadores retornem o 7 como contagem de itens (como o IE8, como Daniel Earwicker apontou) em vez do esperado 6.


Editado:

Encontrei este JSON Validator que valida uma string JSON no RFC 4627 (o tipo de mídia application / json para JavaScript Object Notation) e na especificação da linguagem JavaScript. Atualmente, uma matriz com vírgula à direita é considerada válida apenas para JavaScript e não para a especificação RFC 4627.

No entanto, na especificação RFC 4627, é afirmado que:

2.3 Matrizes

Uma estrutura de matriz é representada como colchetes envolvendo zero ou mais valores (ou elementos). Os elementos são separados por vírgulas.

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

Para mim, isso é novamente um problema de interpretação. Se você escrever que os Elementos são separados por vírgulas (sem declarar algo sobre casos especiais, como o último elemento), pode ser entendido de ambas as maneiras.

O PS RFC 4627 não é um padrão (como explicitamente declarado) e já está obsoleto pelo RFC 7159 (que é um padrão proposto) RFC 7159


6
A regra gramatical fornecida é a mais precisa possível. Não há como ter um value-separatorsem um valuedireito ao lado dele. Além disso, o texto é muito específico. "Separação de valores" só pode ser aplicada se houver vários valores. Portanto, se você tiver dois valores próximos um do outro, eles serão separados por vírgula. Se você tiver um valor (ou se você apenas observar o valor no final), não haverá separação, portanto não haverá vírgula.
Steffen Heil

1

De minha experiência anterior, descobri que diferentes navegadores lidam com vírgulas finais no JSON de maneira diferente.

O Firefox e o Chrome lidam perfeitamente com isso. Mas o IE (todas as versões) parece quebrar. Quero dizer, realmente quebrar e parar de ler o resto do script.

Tendo isso em mente, e também o fato de sempre ser bom escrever código compatível, sugiro que se dedique um esforço extra para garantir que não haja vírgula à direita.

:)


1

Eu mantenho uma contagem atual e a comparo com uma contagem total. Se a contagem atual for menor que a contagem total, eu mostro a vírgula.

Pode não funcionar se você não tiver uma contagem total antes de executar a geração JSON.

Então, novamente, se você estiver usando o PHP 5.2.0 ou melhor, poderá formatar sua resposta usando a API JSON incorporada.


1

Com o JSON relaxado, você pode ter vírgulas à direita ou deixá-las de fora . Eles são opcionais.

Não há razão para que todas as vírgulas precisem estar presentes para analisar um documento semelhante ao JSON.

Dê uma olhada na especificação JSON relaxada e você verá o quão barulhenta é a especificação JSON original. Muitas vírgulas e aspas ...

http://www.relaxedjson.org

Você também pode experimentar seu exemplo usando este analisador RJSON online e vê-lo sendo analisado corretamente.

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


O JSON relaxado não é JSON, portanto, tecnicamente não aplicável.
user2864740

Você pode converter rjson de e para json, para que seja totalmente aplicável. Também é muito fácil adicioná-lo ao seu fluxo de trabalho.
22818 Steven Spungin

Isso pressupõe que os consumidores downstream entendam esse não-JSON. A conversão para JSON válido exigiria a remoção da vírgula nos dois casos.
user2864740

O OP usa uma string para começar. A cadeia de caracteres pode ser analisada para uma json objectutilização JSON.parseou uma biblioteca usando RJSON.parse. Eu concordaria com você se a fonte fosse um objeto, mas esse não é o caso aqui. Não vejo onde na pergunta ele menciona downstreamconsumir um objeto ou string.
Steven Spungin

"Ao gerar manualmente um objeto ou matriz JSON , geralmente é mais fácil deixar uma vírgula à direita no último item do objeto ou matriz. Isso é permitido [ no JSON ]?" - então, novamente: embora este seja um formato alternativo interessante, ele não é JSON e não é tecnicamente aplicável à pergunta sobre JSON . Não há nada para 'defender': é uma proposta Z a questão X.
user2864740

0

Normalmente, faço um loop na matriz e anexo uma vírgula após cada entrada na string. Após o loop, apago a última vírgula novamente.

Talvez não seja o melhor caminho, mas menos caro do que verificar todas as vezes se é o último objeto do circuito, eu acho.


0

Não é recomendado, mas você ainda pode fazer algo assim para analisá-lo.

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


0

Como um loop for é usado para iterar sobre uma matriz ou uma estrutura de dados iterável semelhante, podemos usar o comprimento da matriz como mostrado,

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

Com datafile.txt contendo,

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

0

Como afirmado, não é permitido. Mas em JavaScript, isto é:

var a = Array()
for(let i=1; i<=5; i++) {
    a.push(i)
}
var s = "[" + a.join(",") + "]"

(funciona bem no Firefox, Chrome, Edge, IE11 e sem a permissão do IE9, 8, 7, 5)

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.