Stringhe multilinea in JSON


656

Sto scrivendo alcuni file di dati in formato JSON e vorrei avere alcuni valori di stringa molto lunghi suddivisi su più righe. Usando il modulo JSON di Python ricevo molti errori, sia che io usi \che \ncome fuga.

È possibile avere stringhe multilinea in JSON? È principalmente per il comfort visivo, quindi suppongo che posso solo attivare la parola nel mio editor, ma sono solo un po 'curioso ...



1
strutturare i dati: suddividere la stringa su più righe in una matrice di stringhe, quindi unirle successivamente.
RubyTuesdayDONO

2
Prova lo strumento hjson. Converte la tua stringa multilinea in json nel formato json corretto.
gaurav,

Risposte:


403

JSON non consente interruzioni di riga reali. Devi sostituire tutte le interruzioni di riga con \n.

per esempio:

"first line second line"

può essere salvato con:

"first line\nsecond line"

Nota:

per Python, questo dovrebbe essere scritto come:

"first line\\nsecond line"

dove \\serve per sfuggire alla barra rovesciata, altrimenti python considererà \nil carattere di controllo "nuova riga"


89
-1 L'OP sta usando la sequenza di escape "\ n". Non funziona perché non stanno sfuggendo alla barra rovesciata , come "\\ n", quindi Python sta convertendo la sequenza di fuga in un carattere di nuova riga piuttosto che lasciarla come una barra rovesciata seguita da un en, come richiede JSON.
user359996

6
@ user359996 Non sono sicuro che sia vero. Per me (l'archiviazione dei dati in JSON con il solo \ne l'output tramite Curses), \nsembra funzionare bene. Sembra che dipenda dal motore di visualizzazione / rendering.
ashes999

2
Le sequenze di Newline sono in effetti specifiche della piattaforma (cfr. En.wikipedia.org/wiki/Newline#Representations ). Tuttavia, per @Lightness Races nella risposta di Orbit, né i caratteri di ritorno cursore né quelli di avanzamento riga sono nella grammatica JSON. In realtà non sono un programmatore di Python, quindi non sono sicuro di cosa stia succedendo nel tuo caso, ma o il tuo parser è rotto o non lo passi come pensi. Forse questa risposta lo spiega meglio: stackoverflow.com/a/9295597/359996 . Nota in particolare il bit sul doppio escape.
user359996

5
@Nawaz: "\ n" e "\ r" sono sequenze di escape rispettivamente per avanzamento riga e ritorno a capo. Non sono i letterali di controllo avanzamento riga e ritorno a capo caratteri . Come ulteriore esempio per renderlo più chiaro, considera che "\\" è una sequenza di escape per la barra rovesciata, al contrario di una barra rovesciata letterale. La grammatica JSON esclude esplicitamente i caratteri di controllo (cfr. La definizione "char") e prevede invece la loro rappresentazione tramite sequenze di escape (\\, \ r, \ n, ecc.).
user359996

2
@ user359996: Sì. L'ho visto più tardi, anche se sto mantenendo il mio vecchio commento in quanto tale, nel caso in cui qualcun altro abbia lo stesso dubbio, la nostra discussione potrebbe aiutarli. grazie per averlo confermato BTW.
Nawaz,

197

Ho dovuto fare questo per un piccolo progetto Node.js e ho trovato questo work-around :

{
 "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>"

 ],
}

Mi sembra abbastanza pulito, a parte il fatto che devo usare doppie virgolette ovunque. Anche se altrimenti, forse, potrei usare YAML, ma questo ha altre insidie ​​e non è supportato in modo nativo. Una volta analizzato, uso semplicemente myData.modify_head.join('\n')oppure myData.modify_head.join(), a seconda che voglia un'interruzione di riga dopo ogni stringa o meno.


40
Questa è una soluzione per un'impostazione specifica, non necessariamente correlata alla domanda. Ciò che crei non sono stringhe multilinea (che non sono comunque possibili), ma array con stringhe all'interno
Samuel Rivas,

3
Questo mostra come inserire newline nelle stringhe, che NON rispondono alla domanda. Questa risposta lo fa.
fgrieu,

1
fgrieu - si potrebbe concatenare altrettanto facilmente le stringhe senza aggiungere una nuova riga. Con quella piccola modifica, fornisce una soluzione alternativa per le stringhe multilinea (purché si abbia il controllo della specifica dello schema JSON). Proverò a migliorare la risposta con questo.
drrob

1
Grazie, mi piace Vado con questo per quello su cui sto lavorando. Sembra pulito e organizzato. Ho intenzione di avere ogni nuova riga in questo array implica un'interruzione di riga nel testo emesso, anche se questa soluzione potrebbe funzionare anche nei casi in cui non si inseriscono interruzioni di riga. Ho usato questa soluzione in precedenza nel mio codice sorgente javascript solo perché mi piaceva il modo in cui è organizzata e come non lascia alcun dubbio su quale tipo di spazio bianco entri nella stringa finale.
Gal

Nonostante le riserve dell'inventore JSON, l'ho usato solo per aggiungere commenti (senza la parte javascript, ma solo [] e virgole) per aggiungere commenti per aiutare un possibile manutentore futuro che potrebbe modificare manualmente il mio piccolo file JSON.
Whirl Mind,

117

Sfortunatamente molte delle risposte qui affrontano la domanda su come inserire un carattere di nuova riga nei dati della stringa. La domanda è come rendere il codice più bello suddividendo il valore della stringa su più righe di codice. (E anche le risposte che lo riconoscono forniscono "soluzioni" che presuppongono che uno sia libero di cambiare la rappresentazione dei dati, che in molti casi non lo è.)

E la notizia peggiore è che non esiste una buona risposta.

In molti linguaggi di programmazione, anche se non supportano esplicitamente la suddivisione delle stringhe tra le righe, è comunque possibile utilizzare la concatenazione delle stringhe per ottenere l'effetto desiderato; e fintanto che il compilatore non è terribile, va bene.

Ma json non è un linguaggio di programmazione; è solo una rappresentazione dei dati. Non puoi dirlo per concatenare le stringhe. Né la sua grammatica (abbastanza piccola) include alcuna possibilità per rappresentare una stringa su più righe.

A meno di escogitare un pre-processore di qualche tipo (e io, per esempio, non ho voglia di inventare la mia lingua per risolvere questo problema), non esiste una soluzione generale a questo problema. Se è possibile modificare il formato dei dati, è possibile sostituire una matrice di stringhe. Altrimenti, questo è uno dei numerosi modi in cui JSON non è progettato per la leggibilità umana.


3
Non è chiaro cosa voglia l'OP, newline in stringa o organizzare meglio la stringa ...
9ilsdx 9rvj 0lo

3
@ 9ilsdx9rvj0lo: No, non lo è.
Mark Adelsberger,

Riguardo a "La domanda è come rendere il codice più bello dividendo il valore della stringa su più righe di codice ...": per una soluzione alle istruzioni multilinea in Python, vedi stackoverflow.com/questions/53162/… . C'è una differenza tra JSON multilinea e Python multilinea. JSON multilinea usa '\' seguito da 'n' in JSON, ovvero "\ n" nella stringa. Istruzioni Python su più righe, utilizzare '\' seguito da '\ n', ovvero una barra rovesciata finale sulla riga che deve essere continuata. Formato Windows: sostituire \ n con \ r \ n dove appropriato!
Ivan

106

Controlla le specifiche ! La produzione di caratteri della grammatica JSON può assumere i seguenti valori:

  • any-Unicode-character-salvo- "-or- \-or-control-character
  • \"
  • \\
  • \/
  • \b
  • \f
  • \n
  • \r
  • \t
  • \u quattro cifre esadecimali

I newline sono "caratteri di controllo", quindi no, potresti non avere un newline letterale all'interno della tua stringa. Tuttavia, è possibile codificarlo utilizzando qualsiasi combinazione di \ne \rrichiesta.



3
Questa è la risposta corretta in quanto non lascia ambiguità. Sono consentite nuove linee , secondo le specifiche, purché siano correttamente sfuggite al carattere di controllo.
Ryan

@AliKhaki \ n in JSON non realizzerà il risultato richiesto dalla domanda. O stai pensando a qualcos'altro (cioè incorporando caratteri di nuova riga) o stai parlando di una nuova riga in un letterale stringa (contenente JSON) in un linguaggio di programmazione, che è di nuovo qualcosa di diverso.
Razze di leggerezza in orbita

@LightnessRacesinOrbit sì, cerco newline in stringa
Ali Khaki,

46

JSON non consente le linee di interruzione per la leggibilità.

La tua scommessa migliore è usare un IDE che ti avvolga per te.


1
Un editor come BBEdit che supporta il ritorno a capo "morbido" è l'ideale. Avvolge il testo in modo che appaia tutto nell'area visibile della finestra dell'editor, ma solo i finali di riga digitati (ad esempio, colpire il ritorno a capo) vengono mantenuti nel file quando viene salvato. Semplifica la modifica di JSON con stringhe molto lunghe senza dover ricorrere a trucchi di codice o hack.
cshotton,

44

Questa è una domanda davvero vecchia, ma mi sono imbattuto in una ricerca e penso di conoscere l'origine del tuo problema.

JSON non consente newline "reali" nei suoi dati; può solo essere sfuggito a newline. Vedi la risposta da @YOU . Secondo la domanda, sembra che tu abbia tentato di sfuggire alle interruzioni di linea in Python in due modi: usando il carattere di continuazione della linea ( "\") o usando "\n"come fuga.

Ma tieni a mente: se stai usando una stringa in Python, i caratteri speciali di escape ( "\t", "\n") vengono tradotti in caratteri di controllo REALI! Il"\n" sarà sostituito con il carattere di controllo ASCII che rappresenta un carattere di nuova riga, che è appunto il carattere che è illegale in JSON. (Per quanto riguarda il carattere di continuazione della linea, elimina semplicemente la nuova riga.)

Quindi quello che devi fare è impedire a Python di sfuggire ai personaggi. Puoi farlo usando una stringa non elaborata (posizionata rdavanti alla stringa, come in r"abc\ndef", o includendo una barra aggiuntiva davanti alla newline ( "abc\\ndef").

Entrambi i precedenti, invece di sostituirsi "\n"con il vero carattere di controllo ASCII della nuova riga, lasceranno "\n"come due caratteri letterali, che quindi JSON può interpretare come una fuga di nuova riga.


12

Scrivi il valore della proprietà come una matrice di stringhe. Come esempio riportato qui https://gun.io/blog/multi-line-strings-in-json/ . Questo aiuterà.

Possiamo sempre usare un array di stringhe per stringhe multilinea come segue.

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

E possiamo facilmente iterare l'array per visualizzare i contenuti in modalità multilinea.


1
Vorrei suggerire di aggiungere le informazioni nella risposta dal link, perché i collegamenti potrebbero interrompersi in futuro.
YoungHobbit,

5
Ma loro hai un array, non una stringa. Un array non è una stringa. Periodo.
9ilsdx 9rvj 0lo

Stavo solo pensando a questo. Bello!
Phillip Jacobs,

12

Usa json5 (caricatore) vedi https://json5.org/ - esempio (di json5)

{
  lineBreaks: "Look, Mom! \
No \\n's!",
}

La domanda che l'OP ha posto. Almeno se può usare json5.
nomen

10

È possibile avere stringhe multilinea in JSON?

Sì. Ho appena provato questo ora con il mio browser Web Firefox premendo F12, facendo clic sulla console e digitando nella parte inferiore dello schermo.

x={text:"hello\nworld"}

L'oggetto x è stato appena creato da una stringa in formato JSON contenente una stringa multilinea.

console.log(x.text)
hello
world

x.text viene visualizzato per indicare che si tratta di una stringa a più righe.

Questi due test mostrano che l'interprete Javascript di Firefox è felice di creare e usare JSON con stringhe multilinea.

Altri test con JSON.stringifye JSON.parsedimostrato che l'interprete Javascript può convertire un oggetto contenente stringhe multilinea in JSON e analizzarlo di nuovo senza alcun problema.

In passato ho archiviato le opere complete di Shakespeare come proprietà in un oggetto JSON e poi le ho inviate su Internet, senza essere corrotte.

Esempio

Ecco una stringa di due righe immessa su tre righe

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

Siamo in grado di visualizzare l'oggetto

console.log(x)

dando

Object { text: "experts\nexchange" }

o la stringa

console.log(x.text)

dando

experts
exchange

La fine delle linee nella stringa risulta dall'uso di \ n e le linee di input multiple sono ottenute usando solo \ alla fine della linea.

In pratica potresti voler sincronizzare le tue terminazioni di linea con quelle nella stringa, ad es

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

Lunghezza stringa multi-linea

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

Si noti che la stringa con la nuova riga non è più lunga della stringa con lo spazio. Anche se sulla tastiera sono stati digitati due caratteri ('\' e 'n'), nella stringa è memorizzato solo un carattere.


3
Un lettore di formato di stringa JavaScript non è un lettore di formato di stringa JSON e viceversa, quindi mentre funziona, anche la console JavaScript accetta x={"a":NaN}e x={"a":"a \<literal newline with SHIFT>b"}, che non sono JSON, ma sono JavaScript
cat

9

Usa regex per sostituire tutte le occorrenze di \r\ncon \\n.

Questo ha funzionato per me in scala.

val newstr = str.replace("\r\n", "\\n")

Perché le 3 barre rovesciate?
NeXus,

6
@neXus Non so perché ma qualcuno l'aveva modificato in 3 barre rovesciate. Grazie a LightnessRacesInOrbit per averlo corretto.
Sikander,

5

Se sei disposto a utilizzare Node.js, puoi farlo:

module.exports = {

  multilineStr: `

     dis my life 
     it's now or never

  `

}

puoi importare con Node.js e convertirlo facilmente in JSON in questo modo:

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

e ottieni:

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

come funziona : usi Node.js per caricare un modulo JS, che crea un oggetto JS che può essere facilmente modificato da JSON da Node.js. L'opzione -e valuta la stringa e l' -popzione fa eco al risultato di ritorno dell'ultima operazione Node.js su stdout.

Se vuoi caricare uno script .js che si trova in una diversa directory di lavoro, devi cambiare le stringhe "" e '':

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

-4

Prova a utilizzare il base64valore della stringa codificata. Ha lavorato per me la maggior parte del tempo.

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

dopo la base64stringa codificata sembra

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

la codifica e decodifica base64 è disponibile in tutte le lingue.


7
È necessario un codice speciale per visualizzarlo, stai trasformando una stringa in un array. Non è una soluzione
tom10271

3
Penso che questa sia una cattiva idea: oscura inutilmente il contenuto e richiede codice, tempo, memoria e strumenti aggiuntivi per produrlo e consumarlo. La scansione della stringa e la sostituzione di caratteri speciali ovviamente richiede anche codice, tempo e memoria extra, ma sicuramente meno della codifica e decodifica base64
Semanino,

Questa è una cattiva idea perché la leggibilità di JSON è sparita e anche come menzionato @ tom10271, è necessario un ulteriore intervento per utilizzare il json
T90

-23

metti il ​​testo multilinea sul file txt e poi

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

(funziona su mongoDB)


11
-1: questa è una risposta fuorviante. Non è né JSON valido né funziona in javascript in quanto non esiste alcuna funzione denominata cat.
Martin Schuhfuß,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.