Cadeias de linhas múltiplas em JSON

656

Estou escrevendo alguns arquivos de dados no formato JSON e gostaria de ter alguns valores de string muito longos divididos em várias linhas. Usando o módulo JSON do python, recebo muitos erros, seja eu uso \ou \ncomo uma fuga.

É possível ter strings de várias linhas no JSON? É principalmente para conforto visual, então suponho que posso ativar a quebra de linha no meu editor, mas estou meio curiosa ...

Anonnobody
fonte
2
Possível duplicata de Como lidar com novas linhas em JSON?
Flimzy
1
estruture seus dados: divida a cadeia de linhas múltiplas em uma matriz de cadeias de caracteres e junte-se a elas posteriormente.
RubyTuesdayDONO
2
Experimente a ferramenta hjson. Ele converterá sua String multilinha no json para o formato json apropriado.
precisa saber é
Possível duplicado de Can um valor JSON contém uma cadeia multilinha
Flimzy

Respostas:

403

JSON não permite quebras de linha reais. Você precisa substituir todas as quebras de linha por \n.

por exemplo:

"first line second line"

pode ser salvo com:

"first line\nsecond line"

Nota:

pois Python, isso deve ser escrito como:

"first line\\nsecond line"

onde \\é para escapar da barra invertida; caso contrário, o python tratará \ncomo o caractere de controle "nova linha"

VOCÊ
fonte
89
-1 O OP está usando a sequência de escape "\ n". Como não está escapando da barra invertida , como "\\ n", o Python está convertendo a sequência de escape em um caractere de nova linha, em vez de deixá-la literalmente como uma barra invertida seguida por um en, como o JSON exige.
user359996
6
@ user359996 Não sei se isso é verdade. Para mim (armazenar dados em JSON com just \ne output via Curses), \nparece funcionar bem. Depende do mecanismo de exibição / renderização, ao que parece.
precisa saber é o seguinte
2
As sequências de nova linha são realmente específicas da plataforma (cf. en.wikipedia.org/wiki/Newline#Representations ). No entanto, por @Lightness Races na resposta do Orbit, nem os caracteres de retorno do cursor nem de avanço de linha estão na gramática JSON. Na verdade, eu não sou um programador Python, então não tenho certeza do que está acontecendo no seu caso, mas seu analisador está quebrado ou você não está passando o que pensa que é. Talvez esta resposta o explique melhor: stackoverflow.com/a/9295597/359996 . Observe especialmente o pouco sobre escape duplo.
user359996
5
@Nawaz: "\ n" e "\ r" são seqüências de escape para avanço de linha e retorno de carro, respectivamente. Eles não são o avanço de linha e transporte de retorno de controle literal caracteres . Como um exemplo adicional para deixar mais claro, considere que "\\" é uma sequência de escape para barra invertida, em oposição a uma barra invertida literal. A gramática JSON exclui explicitamente os caracteres de controle (consulte a definição "char") e, em vez disso, fornece sua representação por meio de seqüências de escape (\\, \ r, \ n etc.).
user359996
2
@ user359996: Sim. Vi isso mais tarde, embora eu esteja mantendo meu antigo comentário como tal, caso outra pessoa tenha a mesma dúvida, nossa discussão pode ajudá-los. obrigado por confirmar BTW.
Nawaz
197

Eu tive que fazer isso para um projeto pequeno Node.js e encontrei esta solução alternativa :

{
 "modify_head": [

  "<script type='text/javascript'>",
  "<!--",
  "  function drawSomeText(id) {",
  "  var pjs = Processing.getInstanceById(id);",
  "  var text = document.getElementById('inputtext').value;",
  "  pjs.drawText(text);}",
  "-->",
  "</script>"

 ],

 "modify_body": [

  "<input type='text' id='inputtext'></input>",
  "<button onclick=drawSomeText('ExampleCanvas')></button>"

 ],
}

Isso me parece muito interessante, além disso eu tenho que usar aspas duplas em todos os lugares. Embora contrário, eu poderia, talvez, usar o YAML, mas isso tem outras armadilhas e não é suportado nativamente. Uma vez analisado, apenas uso myData.modify_head.join('\n')ou myData.modify_head.join(), dependendo se desejo uma quebra de linha após cada sequência ou não.

errordeveloper
fonte
40
Esta é uma solução para uma configuração específica, não necessariamente relacionada à pergunta. O que você cria não são seqüências de várias linhas (que não é possível de qualquer maneira), mas matrizes com cordas dentro
Samuel Rivas
3
Isso mostra como inserir uma nova linha em seqüências de caracteres, o que NÃO responde à pergunta. Esta resposta faz.
21135 fgrieu
1
fgrieu - é possível concatenar facilmente as strings sem adicionar uma nova linha. Com essa pequena alteração, ele fornece uma solução alternativa para cadeias de linhas múltiplas (desde que você esteja no controle da especificação do esquema JSON). Vou tentar melhorar a resposta com isso.
drrob
1
Obrigado, eu gosto disso. Estou indo com isso para o que estou trabalhando. Parece limpo e organizado. Vou fazer com que cada nova linha nessa matriz implique uma quebra de linha no texto produzido, embora essa solução também funcione nos casos em que você não insere quebras de linha. Eu já usei essa solução no meu código-fonte javascript apenas porque gostei da aparência organizada e de como não deixa dúvidas sobre quais tipos de espaço em branco entram na sequência final.
Gal
Não obstante as reservas do inventor JSON, eu apenas usei isso para adicionar comentários (sem a parte javascript, mas apenas as [] e vírgulas) para adicionar comentários para ajudar um possível mantenedor futuro que possa editar manualmente meu pequeno arquivo JSON.
Giro Mente
117

Infelizmente, muitas das respostas aqui abordam a questão de como colocar um caractere de nova linha nos dados da string. A questão é como tornar o código mais bonito, dividindo o valor da string em várias linhas de código. (E mesmo as respostas que reconhecem isso fornecem "soluções" que pressupõem a liberdade de alterar a representação dos dados, o que em muitos casos não é.)

E a pior notícia é que não há uma boa resposta.

Em muitas linguagens de programação, mesmo que elas não suportem explicitamente a divisão de cadeias por linhas, você ainda pode usar a concatenação de cadeias para obter o efeito desejado; e enquanto o compilador não for horrível, tudo bem.

Mas json não é uma linguagem de programação; é apenas uma representação de dados. Você não pode dizer para concatenar seqüências de caracteres. Sua gramática (bastante pequena) também não inclui nenhum recurso para representar uma sequência em várias linhas.

Com a falta de criar um pré-processador de algum tipo (e eu, por exemplo, não tenho vontade de criar meu próprio idioma para resolver esse problema), não há uma solução geral para esse problema. Se você puder alterar o formato dos dados, poderá substituir uma matriz de seqüências de caracteres. Caso contrário, essa é uma das inúmeras maneiras pelas quais o json não é projetado para facilitar a leitura por humanos.

Mark Adelsberger
fonte
3
Não está claro o que o OP quer, novas linhas na string ou organizar melhor a string ... #
9ilsdx 9rvj 0lo
3
@ 9ilsdx9rvj0lo: Não, não é.
Mark Adelsberger
Em relação a "A questão é como tornar o código mais bonito, dividindo o valor da string em várias linhas de código ...": para obter uma solução para instruções de várias linhas em Python, consulte stackoverflow.com/questions/53162/… . Há uma diferença entre JSON de várias linhas e Python de várias linhas. O JSON de várias linhas usa '\' seguido de 'n' no JSON, ou seja, "\ n" na string. Instruções Python com várias linhas, use '\' seguido de '\ n', isto é, uma barra invertida à direita na linha que deve ser continuada. Formato Windows: substitua \ n por \ r \ n onde apropriado!
Ivan
106

Confira a especificação ! A produção de caracteres da gramática JSON pode assumir os seguintes valores:

  • qualquer caractere Unicode, exceto, "ou \-ou-ou-controle-caractere
  • \"
  • \\
  • \/
  • \b
  • \f
  • \n
  • \r
  • \t
  • \u quatro dígitos hexadecimais

As novas linhas são "caracteres de controle"; portanto, não, você pode não ter uma nova linha literal dentro da sua string. No entanto, você pode codificá-lo usando qualquer combinação \ne \rnecessidade.

Raças de leveza em órbita
fonte
3
Esta é a resposta correta, pois não deixa ambiguidade. Novas linhas são permitidas, de acordo com a especificação, desde que sejam adequadamente escapadas com o caractere de controle.
23717 Ryan
O @AliKhaki \ n no JSON não alcançará o resultado desejado pela pergunta. Ou você está pensando em outra coisa (por exemplo, incorporando caracteres de nova linha) ou está falando de uma nova linha em uma literal de cadeia de caracteres (contendo JSON) em alguma linguagem de programação, o que é novamente algo diferente.
Corridas da Luz em Órbita
@LightnessRacesinOrbit sim eu à procura de nova linha em seqüência
Ali Cáqui
46

JSON não permite quebrar linhas para facilitar a leitura.

Sua melhor aposta é usar um IDE que contorne a linha para você.

James Gentes
fonte
1
Um editor como o BBEdit que suporte quebra automática de linha "suave" é ideal. Ele agrupa o texto para que tudo apareça na área visível da janela do editor, mas apenas as terminações de linha digitadas (por exemplo, pressionando o retorno de carro) permanecem no arquivo quando ele é salvo. Facilita a edição do JSON com sequências muito longas, sem a necessidade de recorrer a truques ou hacks de código.
precisa saber é o seguinte
44

Essa é uma pergunta muito antiga, mas me deparei com isso em uma pesquisa e acho que conheço a origem do seu problema.

JSON não permite novas linhas "reais" em seus dados; só pode ter escapado de novas linhas. Veja a resposta de @YOU . De acordo com a pergunta, parece que você tentou escapar de quebras de linha no Python de duas maneiras: usando o caractere de continuação de linha ( "\") ou usando "\n"como escape.

Mas lembre-se: se você estiver usando uma string em python, caracteres especiais com escape ( "\t", "\n") serão convertidos em caracteres de controle REAL! O "\n"será substituído pelo caractere de controle ASCII que representa um caractere de nova linha, que é precisamente o caractere que é ilegal no JSON. (Quanto ao caractere de continuação de linha, ele simplesmente retira a nova linha.)

Então, o que você precisa fazer é impedir que o Python escape de caracteres. Você pode fazer isso usando uma string bruta (colocada rna frente da string, como em r"abc\ndef", ou incluindo uma barra extra na frente da nova linha ( "abc\\ndef").

Ambas as opções acima, em vez de substituir "\n"pelo caractere de controle ASCII da nova linha real, deixarão "\n"como dois caracteres literais, que, em seguida, o JSON pode interpretar como um escape da nova linha.

HardlyKnowEm
fonte
12

Escreva o valor da propriedade como uma matriz de seqüências de caracteres. Como exemplo dado aqui https://gun.io/blog/multi-line-strings-in-json/ . Isso vai ajudar.

Sempre podemos usar uma matriz de seqüências de caracteres para sequências de várias linhas, como a seguir.

{
    "singleLine": "Some singleline String",
    "multiline": ["Line one", "line Two", "Line Three"]
} 

E podemos iterar facilmente o array para exibir o conteúdo de várias linhas.

Sandip Nirmal
fonte
1
Gostaria de sugerir que você adicione as informações em sua resposta no link, Como os links podem quebrar no futuro.
precisa saber é o seguinte
5
Mas eles têm uma matriz, não uma string. Uma matriz não é uma sequência. Período.
9ilsdx 9rvj 0lo
Só estava pensando nisso. Agradável!
Phillip Jacobs
12

Use json5 (loader), consulte https://json5.org/ - exemplo (por json5)

{
  lineBreaks: "Look, Mom! \
No \\n's!",
}
Lacom
fonte
A pergunta que o OP fez. Pelo menos se ele puder usar o json5.
Nomen
10

É possível ter strings de várias linhas no JSON?

Sim. Acabei de testar isso agora com o meu navegador Firefox pressionando F12, clicando no console e digitando na parte inferior da tela.

x={text:"hello\nworld"}

O objeto x acaba de ser criado a partir de uma sequência de formato JSON contendo uma sequência de várias linhas.

console.log(x.text)
hello
world

O x.text é exibido mostrando que é uma sequência de várias linhas.

Esses dois testes mostram que o intérprete Javascript do Firefox tem prazer em criar e usar JSON com seqüências de várias linhas.

Mais testes com JSON.stringifyeJSON.parse mostrou que o interpretador Javascript pode converter um objeto contendo seqüências de linhas múltiplas em JSON e analisá-lo novamente sem nenhum problema.

No passado, eu armazenei as obras completas de Shakespeare como uma propriedade em um objeto JSON e as enviei pela Internet, sem corrupção.

Exemplo

Aqui está uma sequência de duas linhas inserida em três linhas

x={text:"expert\
s\nex\
change"}

Nós podemos exibir o objeto

console.log(x)

dando

Object { text: "experts\nexchange" }

ou a corda

console.log(x.text)

dando

experts
exchange

O final das linhas na string resulta do uso de \ n e as várias linhas de entrada são obtidas usando apenas \ no final da linha.

Na prática, você pode querer sincronizar as terminações da sua linha com as da string, por exemplo

x={text:"experts\n\
exchange"}

Comprimento da corda de várias linhas

console.log("Hello\nWorld".length)
11 
console.log("Hello World".length)
11

Observe que a sequência com a nova linha não é maior que a sequência com o espaço. Mesmo que dois caracteres tenham sido digitados no teclado ('\' e 'n'), apenas um caractere é armazenado na string.

Ivan
fonte
3
A JavaScript leitor de formato de cadeia não é um leitor de formato de cadeia JSON e vice-versa, por isso, enquanto isso acontece com o trabalho, o console JavaScript também aceita x={"a":NaN}e x={"a":"a \<literal newline with SHIFT>b"}, que não são JSON, mas são JavaScript
gato
9

Use regex para substituir todas as ocorrências de \r\npor \\n.

Isso funcionou para mim na Scala.

val newstr = str.replace("\r\n", "\\n")
Sikander
fonte
Por que as três barras invertidas?
NeXus
6
@neXus Eu não sei por que, mas alguém tinha editado para 3 barras invertidas. Agradecimentos a LightnessRacesInOrbit por corrigi-lo.
Sikander
5

Se você estiver disposto a usar o Node.js, poderá fazer o seguinte:

module.exports = {

  multilineStr: `

     dis my life 
     it's now or never

  `

}

você pode importar com o Node.js e convertê-lo para JSON facilmente da seguinte forma:

echo `node -pe 'JSON.stringify(require("./json-mod.js"))'`

e você obtém:

{"multilineStr":"\n \n dis my life\n it's now or never\n \n "}

como funciona : você usa o Node.js para carregar um módulo JS, que cria um objeto JS que pode ser facilmente JSON stringificado por Node.js. A opção -e avalia a sequência e a -popção ecoa o resultado do retorno da última operação do Node.js. para stdout.

Se você deseja carregar um script .js que esteja em um diretório de trabalho diferente, é necessário alternar as seqüências "" e '':

my_script='../json-mod.js'
echo `node -pe "JSON.stringify(require('$my_script'))"`
Alexander Mills
fonte
-4

Tente usar o base64valor da string codificada. Trabalhou para mim na maioria das vezes.

{
    "singleLine": "Some singleline String",
    "multiline": ["Line one", "line Two", "Line Three"]
} 

depois da base64string codificada parecer

{
    "singleLine": "Some singleline String",
    "multiline": "TGluZSBvbmUKTGluZSBUd28KTGluZSBUaHJlZQ=="
} 

A codificação e decodificação base64 está disponível em todos os idiomas.

Sunit Parekh
fonte
7
Você precisa de um código especial para exibi-lo, está transformando uma string em uma matriz. Não é uma solução
tom10271 14/05
3
Eu acho que é uma péssima idéia - ele ofusca o conteúdo desnecessariamente e requer código, tempo, memória e ferramentas extras para produzi-lo e consumi-lo. A digitalização através da corda e substituir caracteres especiais, claro, requer código extra, tempo e memória, também, mas definitivamente menos de base64 codificação e decodificação
Semanino
Essa é uma péssima idéia, porque a legibilidade do JSON se foi e, também como @ tom10271 mencionado, você precisa de uma operação extra para usar o json
T90
-23

coloque o texto multilinha no arquivo txt e depois

var str = {
    text: cat('path_to_file/text.txt')
}

(funciona no mongoDB)

flaalf
fonte
11
-1: esta é uma resposta enganosa. Não é um JSON válido nem funciona em javascript, pois não há nenhuma função nomeada cat.
Martin Schuhfuß