Pular para o conteúdo principal

Converter XML em JSON

O XML para JSON converte um documento no seu navegador. Não existe um mapeamento canônico entre os dois formatos, então cada decisão é uma opção, e não um padrão silencioso — a mais importante é a lista force-array, porque o XML não distingue uma lista de um item de um valor único, e nenhum conversor consegue inferir isso.

Só local
XML
0 B1 linhaLin. 1, Col. 1
JSONsomente leitura
0 B1 linha

Como funciona o Converter XML em JSON?

XML e JSON não descrevem as mesmas formas, então não existe uma única tradução correta entre eles. Um conversor que apresenta uma assim mesmo está escondendo quatro decisões, cada uma capaz de corromper os seus dados em silêncio.

O problema do elemento único, que não dá para inferir

O XML não tem arrays. <line/><line/> são dois elementos; <line/> é um. Um conversor transforma elementos repetidos em array e deixa um elemento solto como escalar — o que significa que o mesmo endpoint produz {"line": {…}} para um pedido com uma linha e {"line": [{…}, {…}]} para um pedido com duas. Código escrito para o segundo quebra no primeiro, em produção, no dia em que um cliente pede uma única coisa.

Isso não se resolve por inferência. A informação necessária — este elemento é uma coleção? — mora no esquema, não na instância. A correção honesta é a lista force-array: nomeie os elementos que são coleções e eles serão sempre arrays, não importa quantos deles o documento tenha hoje.

Atributos precisam de um lugar para ir

<line sku="X"><sku>Y</sku></line> tem um atributo e um elemento filho com o mesmo nome. Mesclá-los perde um dos dois. O prefixo — @ por padrão — preserva os dois, ao custo de chaves um pouco incômodas de digitar em JavaScript. Defina-o como vazio para mesclá-los e aceitar a colisão.

O XML não tem tipos

<qty>3</qty> é a string "3". Forçá-lo a número é um palpite, e é esse palpite que transforma o número de peça 007 em 7 e o CEP 01970 em 1970. O parsing de valores fica desligado por padrão e, quando ligado, um zero à esquerda ainda mantém o valor como string — a gramática do JSON proíbe zeros à esquerda de qualquer forma, então não há nada a perder.

Conteúdo misto não sobrevive

<p>before<b>bold</b>after</p> tem texto antes e depois de um filho. Objetos JSON não têm ordem, então os dois trechos de texto são unidos sob uma chave e a posição deles em relação ao <b> se perde. Nada conserta isso; XML em forma de documento não é dado em forma de dados, e convertê-lo para JSON é a escolha errada, e não apenas uma conversão com perdas.

Entrada malformada é rejeitada, não adivinhada

Tags mal emparelhadas e elementos não fechados geram um erro que nomeia a tag e a linha. Um conversor que aceita <a><b></a> e emite JSON de aparência plausível é pior do que um que falha, porque quem colou XML truncado nunca fica sabendo de que ele estava truncado.

XML

<order id="1">
  <line sku="A">Widget</line>
</order>

JSON

{
  "order": {
    "@id": "1",
    "line": {
      "@sku": "A",
      "#text": "Widget"
    }
  }
}
// with "line" forced: "line": [ … ]

Quais opções e casos-limite o Converter XML em JSON suporta?

Referência técnica e opções
ParâmetroTipoPadrãoComportamento e casos-limite
Forçar arraynomes de elementos(nenhum)Os nomes nesta lista são sempre arrays, mesmo com uma única ocorrência. A opção mais importante de todas: é o único conserto para o problema da lista de um item, e não dá para inferir pelo documento.
Prefixo de atributostring@Mantém os atributos distintos dos elementos filhos de mesmo nome. Deixe vazio para mesclá-los, aceitando que, numa colisão, um deles ganha.
Chave de textostring#textPara onde vai o texto de um elemento quando ele também tem atributos ou filhos. Um elemento com apenas texto vira uma string pura e simples.
Interpretar valoresbooleanodesligadoConverte "3" em 3, "true" em true e "null" em null. Desligado por padrão porque XML não tem tipos, e adivinhar transforma números de peça em inteiros.
Zeros à esquerdamantidos como stringsempre007 continua "007" mesmo com a interpretação de valores ligada. A gramática do JSON proíbe zero à esquerda, então não existe representação de destino que o preserve.
Remover namespacesbooleanodesligadoElimina os prefixos, de modo que soap:Envelope vira Envelope, e remove as declarações xmlns. Conveniente para SOAP; com perdas se dois namespaces usam o mesmo nome local.
Manter comentáriosbooleanodesligadoPreserva os comentários sob um membro #comment. A posição deles entre os elementos não se preserva, porque objetos JSON não têm ordem.
Elementos vaziosnullsempre<a/> e <a></a> são a mesma coisa em XML, e ambos viram null em vez de string vazia, que daria a entender que existe um valor.
CDATAtexto literal—O conteúdo dentro de CDATA é tomado ao pé da letra: um < ali é um e comercial seguido de lt, não um sinal de menor. É exatamente para isso que CDATA existe.
Entidadesdecodificadasas cinco predefinidas& < > " ' mais as referências numéricas. Uma entidade não declarada fica como está em vez de ser apagada, porque apagar conteúdo em silêncio é a falha pior.

Perguntas frequentes

Por que um item é um objeto, mas dois itens são um array?

Porque o XML não tem arrays, e esse é o maior perigo de todos ao convertê-lo. Um conversor vê um <line> e não sabe se o esquema permite mais. Coloque o nome do elemento na caixa force-array e ele se torna um array todas as vezes — e é contra isso que o seu código precisa ser escrito. Isso vale ser feito antes de você entregar, e não depois de um pedido de um item só quebrar a produção.

Por que minhas chaves começam com @?

São os atributos. O XML tem dois tipos de membro e o JSON tem um, então os atributos precisam de um prefixo, ou colidem com elementos filhos — e um elemento que tem tanto um atributo sku quanto um filho sku não é nada incomum. Você pode definir o prefixo como vazio para mesclá-los, ou trocá-lo por algo mais amigável, como um sublinhado.

Por que meus números são strings?

Porque em XML eles são strings. Não há informação de tipo no documento, então converter <qty>3</qty> no número 3 é um palpite que por acaso acerta quantidades e erra números de peça, CEPs e telefones. Ative o parsing de valores se os seus dados não têm identificadores com zero à esquerda; mesmo assim, um zero à esquerda mantém o valor como string.

O que aconteceu com o texto em volta dos meus elementos filhos?

Ele foi unido e colocado sob a chave text, e a posição se perdeu. Isso é conteúdo misto, e o JSON genuinamente não consegue representá-lo: um objeto não tem ordem, então não há onde registrar que um texto veio antes de um filho e outro depois. Se o seu XML é em forma de documento — XHTML, DocBook, qualquer coisa com marcação dentro de prosa —, convertê-lo para JSON é a operação errada, e não apenas uma conversão com perdas.

Ele lida com respostas SOAP?

Sim, e ative a opção strip namespaces, que é o que transforma soap:Envelope em Envelope e remove as declarações xmlns que, de outro modo, apareceriam como atributos em todos os elementos. Saiba que remover é com perdas se o documento realmente usa dois namespaces com o mesmo nome local — raro em SOAP e comum em XML de vocabulários misturados.

Meu XML é enviado?

Não. O tokenizador e o conversor rodam ambos na aba que você já tem aberta — confira no painel Network. Isso importa porque o XML que trafega hoje é majoritariamente SOAP, asserções SAML e mensagens financeiras, ou seja, parte do material mais sensível que uma pessoa desenvolvedora manuseia.