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

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

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

dando-lhe uma string como

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

Isso é permitido?

321
Curiosamente (ou horrivelmente) no IE 8, acabei de descobrir que o alerta ([1, 2, 3,]. Length) exibirá "4".
adicionado o autor Daniel Earwicker, fonte
Eu também estava me perguntando isso, então é uma pergunta perfeitamente razoável.
adicionado o autor hoju, fonte
Em resposta à ideia de usar o SO como um marcador social para questões de programação comuns: o que poderia estar errado ao adicionar conteúdo que inevitavelmente trará mais programadores (e sua especialização) para o site?
adicionado o autor dclowd9901, fonte
Como o Jeff disse, eu acho que é perfeitamente bom usar o SO como um 'caderno' de coisas que você teve que gastar algum tempo olhando para cima. Claro, este é o fim simples desses tipos de itens, mas eu ainda acho que é apropriado, especialmente desde que os diferentes mecanismos de JavaScript lidam com isso de forma diferente.
adicionado o autor pkaeding, fonte
@DanielEarwicker: Irrelevante, já que não é JSON.
adicionado o autor Lightness Races in Orbit, fonte
Se o JSON não é para mecanismos Javascript, por que é o nome "JavaScript Object Notation"?
adicionado o autor James Curran, fonte
Foi algo que precisei pesquisar na Web há alguns dias. Eu não vi uma resposta aqui no SO, então, seguindo a missão do site, fiz a pergunta e respondi para que outros pudessem encontrá-la. Isso é algo que Jeff explicitamente disse que queria fazer aqui.
adicionado o autor Ben Combee, fonte
Obrigado! Eu não queria remover a tag eu mesmo.
adicionado o autor Ben Combee, fonte
Mas mais uma coisa: por que o OP está escrevendo o JSON manualmente? Isso é um anti-padrão claro - deve-se sempre usar uma biblioteca para gerar JSON ou converter para/de estrutura de objeto que a linguagem possui. Usar a concatenação de strings só está pedindo problemas; não apenas por vírgulas, mas por codificação, escape, aninhamento incorreto. É exatamente tão ruim quanto usar manipulação de strings ou regexps para XML.
adicionado o autor StaxMan, fonte
Com algo tão básico que a resposta é encontrada olhando para a especificação oficial, isso soa mais como pescar pontos do que fornecer respostas úteis para problemas não resolvidos. Desculpe cara.
adicionado o autor eyelidlessness, fonte
Por que vale a pena, a minha queixa não é que a pergunta é simples (respondi de bom grado a uma série de perguntas simples aqui), mas que parecia (à primeira vista) uma questão destinada a pontos de reputação de jogo. Você também notará que eu concordei que a pergunta é válida depois de alguma discussão.
adicionado o autor eyelidlessness, fonte
Eu removi a tag de pergunta artificial porque é evidente que isso não é tão conhecido como deveria ser, apesar do fato de que é explicitamente detalhado na especificação oficial.
adicionado o autor eyelidlessness, fonte
Porque os literais de objeto Javascript inspiraram o formato. Você não acha que está dizendo que os mecanismos JS estão apenas começando a ter recursos JSON integrados? simonwillison.net/2006/Dec/20/json Mas o JSON tem muitas restrições não imposta por JS, por exemplo. Os literais de objeto JS não exigem chaves entre aspas.
adicionado o autor eyelidlessness, fonte
Além disso, os mecanismos JS tratam de forma diferente do fato de que o JS não entende (atualmente) o JSON e simplesmente o trata como um literal de objeto/matriz. A diferença é uma diferença no tratamento do mecanismo de literais de objeto/matriz, que não são iguais aos do JSON.
adicionado o autor eyelidlessness, fonte
O JSON não é para mecanismos Javascript, é um formato de intercâmbio de dados universal. Não há espaço para erro na resposta à pergunta, porque está claramente especificado.
adicionado o autor eyelidlessness, fonte
Se é algum consolo, eu não fiz o downvote, apenas adicionei a tag porque achei que era apropriado.
adicionado o autor eyelidlessness, fonte
Concordou que esta é uma boa pergunta para postar. Eu cheguei aqui pesquisando a questão.
adicionado o autor fool4jesus, fonte

14 Respostas

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

Em geral eu tento inverter o problema e adicionar a vírgula antes do valor real, então você acaba com o código que se parece com isso:

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 extra de código no loop for dificilmente é cara ...

Another alternative I've used when output a structure to JSON from a dictionary of some form is to always append a comma after each entry (as you are doing above) and then add a dummy entry at the end that has not trailing comma (but that is just lazy ;->).

Não funciona bem com um array, infelizmente.

179
adicionado
É realmente uma pena que o ECMA5 especifique trailings, mas o JSON não.
adicionado o autor FlavorScape, fonte
ótima dica sobre como adicionar uma entrada fictícia no final!
adicionado o autor dcsan, fonte
Sim, essa linha extra dificilmente é cara, mas um incômodo, no entanto.
adicionado o autor René Nyffenegger, fonte
Essa abordagem funciona para loops for indexados. Que tal para ... em loops de estilo? Existe uma maneira elegante?
adicionado o autor sam, fonte
Se você gosta de código ofuscado, você pode evitar o acréscimo adicional assim: s.appendF (& ", \"% d \ "" [! I], i); . Você pode simplificá-lo para "…" +! I , mas o compilador pode avisar sobre aritmética de string.
adicionado o autor Marcelo Cantos, fonte
Boa resposta. Por favor, forneça "prova" (um link para documentos, especificações, etc.) da sua resposta.
adicionado o autor chharvey, fonte
Bem, agora eu tenho uma tarefa para escrever uma árvore de sintaxe em uma forma de JSON enquanto é gerada por um autômato de pilha. Eu não posso usar esse truque, infelizmente.
adicionado o autor Calmarius, fonte
Existe uma maneira de fazer o Firefox se comportar como o IE a esse respeito e produzir um erro ou pelo menos avisar quando uma vírgula final for encontrada? Eu desenvolvo principalmente no Firefox, então seria bom ser notificado sobre este problema o mais rápido possível.
adicionado o autor Michael Butler, fonte
Atualizada a resposta para responder explicitamente à pergunta. Eu concordo, minha resposta inicial ignorou o explícito "não".
adicionado o autor brianb, fonte
Essa linha extra de código pode ser complicada ao lidar com propriedades. Você pode se deparar com toneladas de if s apenas para evitar essa pequena vírgula estúpida. Sobre expensiveness YMMV, veja isto por exemplo jsfiddle.net/oriadam/mywL9384 Esclarecimento: sua solução é ótima Eu odeio especificações que proíbem uma vírgula à direita.
adicionado o autor oriadam, fonte
Eu 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 as vírgulas extras muito mais fáceis de detectar e economiza muito tempo. É chato, eu gostaria que houvesse uma opção para lançar um erro para isso com o firefox (já que isso ajudaria na depuração).
adicionado o autor rocketmonkeys, fonte

Não. As especificações do JSON, conforme mantidas em http://json.org , não permitem vírgulas à direita. Pelo que vi, alguns analisadores podem silenciosamente permitir que eles leiam uma string JSON, enquanto outros lançarão erros. Para interoperabilidade, você não deve incluí-lo.

O código acima pode ser reestruturado, seja para remover a vírgula final quando adicionar o terminador de matriz ou para adicionar a vírgula antes dos itens, ignorando isso para o primeiro.

113
adicionado
E esta é a resposta correta para a pergunta.
adicionado o autor cdiggins, fonte
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.
adicionado o autor Zero Distraction, fonte
@ 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, CSV ou YAML. Eles não são a mesma coisa. O JSON não existe no EXMA262, mas a sintaxe derivada dele é chamada de notação literal do objeto (o ON em JSON).
adicionado o autor slebetman, fonte
Ser ECMAScript válido não significa necessariamente que um documento é válido JSON - JSON é geralmente definido em RFC 4627 , e essa especificação não permite a vírgula final.
adicionado o autor Tim Gilbert, fonte

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

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

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

96
adicionado
Isso é o que eu normalmente faço em situações como essa; Eu 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 .
adicionado o autor Lawrence Dol, fonte
Além disso, é melhor conter o escopo do separador: para (let ..., sep = ""; ...; sep = ",") {...
adicionado o autor Lawrence Dol, fonte
Eu não gosto dessa solução, pois há outra variável poluindo meu escopo. Um if é mais fácil de entender. Mas obrigado por compartilhar.
adicionado o autor Ich, fonte

Vírgulas à direita são permitidas em JavaScript, mas não funcionam no IE. A especificação JSON sem versão de Douglas Crockford não permitia, e como não tinha versão, isso não deveria mudar. A especificação JSON do ES5 permitiu que eles fossem uma extensão, mas o RFC 4627 de Crockford não o fez, e o ES5 reverteu para não permitir. Firefox seguiu o exemplo. O Internet Explorer é o motivo pelo qual não podemos ter coisas boas.

15
adicionado
Eu apenas tentei no IE 11 sem nenhum problema. Em quais versões do IE você testou, onde encontrou problemas?
adicionado o autor iconoclast, fonte
Parece que Crockford é o motivo pelo qual não podemos ter coisas boas. Isso e comentários em JSON
adicionado o autor Hejazzman, fonte
adicionado o autor Tobu, fonte

Os codificadores PHP podem querer dar uma olhada em implode() . Isso leva uma matriz une-se usando uma string.

Dos documentos ...

$array = array('lastname', 'email', 'phone');
echo implode(",", $array);//lastname,email,phone
11
adicionado
Da mesma forma, o JavaScript tem join() . A maioria das linguagens tem um método similar, ou um similar pode ser facilmente codificado.
adicionado o autor Dan Burton, fonte
PHP tem json_encode, que lida com todos os detalhes de fazer JSON, não apenas vírgulas.
adicionado o autor Brilliand, fonte
A maioria das linguagens, exceto Java.
adicionado o autor Robert, fonte

As it's been already said, JSON spec (based on ECMAScript 3) doesn't allow trailing comma. ES >= 5 allows it, so you can actually use that notation in pure JS. It's been argued about, and some parsers did support it (http://bolinfest.com/essays/json.html, http://whereswalden.com/2010/09/08/spidermonkey-json-change-trailing-commas-no-longer-accepted/), but it's the spec fact (as shown on http://json.org/) that it shouldn't work in JSON. That thing said...

... Estou me perguntando por que ninguém apontou que você pode realmente dividir o loop na 0th iteration e usar a vírgula leading em vez de um para eliminar o cheiro do código de comparação e qualquer desempenho real sobrecarga no loop, resultando em um código que é realmente mais curto, mais simples e mais rápido (devido a não ramificação/condicionais no loop) do que outras soluções propostas.

Por exemplo. (em um pseudocódigo do tipo 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("]");
8
adicionado

Interestingly, both C & C++ (and I think C#, but I'm not sure) specifically allow the trailing comma -- for exactly the reason given: It make programmaticly generating lists much easier. Not sure why JavaScript didn't follow their lead.

6
adicionado
O PHP também permite isso. Eu acho que é o único recurso do PHP que eu gosto. p
adicionado o autor iconoclast, fonte
As vírgulas à direita funcionam no Firefox, mas não no IE.
adicionado o autor kzh, fonte
O ECMA especificou explicitamente que as vírgulas à direita são permitidas nas próximas especificações: ejohn.org/blog/bug-fixes-in-javascript-2 Mais uma razão para deixar claro que JSON! = Objeto JS.
adicionado o autor eyelidlessness, fonte

Use JSON5. Não use JSON.

  • Objetos e matrizes podem ter vírgulas à direita </​​li>
  • As chaves de objeto podem não ser exibidas se forem identificadores válidos
  • As strings podem ser citadas com uma só citação
  • 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 (inicial ou final).
  • Os números podem incluir Infinity e -Infinity.
  • Os números podem começar com um sinal de mais (+) explícito.
  • Os comentários em linha (linha única) e bloco (multilinha) são permitidos.

http://json5.org/

https://github.com/aseemk/json5

5
adicionado
Além disso, as seqüências de caracteres mutliline são terríveis. Eu sonho com as multilinhas do ES6.
adicionado o autor Marco Sulla, fonte
Parece bom, mas não adicionar novos tipos de dados parece uma oportunidade perdida ... claro que o desejo de permanecer um subconjunto restrito de ECMAScript 5 força isso, mas ainda assim ...
adicionado o autor iconoclast, fonte
Não, isso é um conselho HORRÍVEL. De todas as bibliotecas JSON existentes, muito poucas suportam essa extensão; e tudo isso por "melhorias" muito questionáveis. Por favor, NÃO cause mais erosão da interoperabilidade por novas extensões falsas como esta.
adicionado o autor StaxMan, fonte
Eu acredito que gastar sua vida em corrigir vírgulas é mais horrível.
adicionado o autor user619271, fonte

Eu mantenho uma contagem atual e a comparo a uma contagem total. Se a contagem atual for menor que a contagem total, exibirei 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ê está usando PHP 5.2.0 ou melhor, você pode simplesmente formatar sua resposta usando a API JSON embutida.

1
adicionado

Da minha experiência passada, descobri que navegadores diferentes lidam com vírgulas à direita no JSON de forma diferente.

Tanto o Firefox quanto o Chrome lidam bem com isso. Mas o IE (todas as versões) parece quebrar. Quero dizer realmente quebrar e parar de ler o resto do roteiro.

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

:)

1
adicionado

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

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

Então, pelo que entendi, deveria 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 dos 6 esperados.


Editado:

Eu encontrei este JSON Validator que valida uma string JSON contra RFC 4627 (O tipo de mídia do aplicativo/json para JavaScript Object Notation) e contra a especificação da linguagem JavaScript. Na verdade, aqui uma matriz com uma vírgula final é 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 ao redor de zero   ou mais valores (ou elementos). Os elementos são separados por vírgulas.

 array = begin-array [valor * (valor do valor-separador)] end-array
 

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

P.S. RFC 4627 isn't a standard (as explicitly stated), and is already obsolited by RFC 7159 (which is a proposed standard) RFC 7159

1
adicionado
A regra gramatical dada é tão precisa quanto você pode obter. Não há como ter um valor-separador sem um valor bem próximo a ele. Além disso, o texto é muito específico. "Separação de valores" só pode ser aplicada se houver vários valores. Então, se você tem dois valores próximos um do outro, eles são separados usando uma vírgula. Se você tiver um valor (ou se você observar apenas o valor no final), não haverá separação, portanto, nenhuma vírgula.
adicionado o autor Steffen Heil, fonte

Eu costumo fazer um loop sobre o array e anexar uma vírgula após cada entrada na string. Depois do loop eu apago a última vírgula novamente.

Talvez não o melhor caminho, mas menos caro do que verificar cada vez se é o último objeto no loop, eu acho.

0
adicionado

Com o JSON relaxado, você pode ter vírgulas à direita ou simplesmente deixar as vírgulas . Eles são opcionais.

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

Dê uma olhada nas especificações do JSON Relaxed e você verá como a especificação JSON original é "barulhenta". Muitas vírgulas e citações ...

http://www.relaxedjson.org

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

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

0
adicionado

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

<div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false"> <div class="snippet-code">

jsonStr = '[0,1,2,3,4,5,]';
let data;
eval('data = ' + jsonStr);
console.log(data)
</div> </div>
0
adicionado
JavaScript Brasil OFICIAL
JavaScript Brasil OFICIAL
4 138 dos participantes

Grupo sobre JavaScript do Brasil