Mehrzeilige Zeichenfolgen in JSON

653

Ich schreibe einige Datendateien im JSON-Format und möchte einige wirklich lange Zeichenfolgenwerte über mehrere Zeilen verteilt haben. Mit dem JSON-Modul von Python erhalte ich viele Fehler, egal ob ich es benutze \oder \nals Escape.

Ist es möglich, mehrzeilige Zeichenfolgen in JSON zu haben? Es dient hauptsächlich dem visuellen Komfort, also kann ich wohl den Zeilenumbruch in meinem Editor aktivieren, aber ich bin nur ein bisschen neugierig ...

Anonnobody
quelle
2
Mögliches Duplikat von Wie gehe ich mit Zeilenumbrüchen in JSON um?
Flimzy
1
Strukturieren Sie Ihre Daten: Teilen Sie die mehrzeilige Zeichenfolge in ein Array von Zeichenfolgen auf und verbinden Sie sie später.
RubyTuesdayDONO
2
Versuchen Sie es mit dem hjson-Tool. Es konvertiert Ihren mehrzeiligen String in json in das richtige json-Format.
Gaurav

Antworten:

400

JSON erlaubt keine echten Zeilenumbrüche. Sie müssen alle Zeilenumbrüche durch ersetzen \n.

z.B:

"first line second line"

kann gespeichert werden mit:

"first line\nsecond line"

Hinweis:

denn Pythondies sollte geschrieben werden als:

"first line\\nsecond line"

wo \\ist für das Entkommen des Backslash, sonst behandelt Python \nals Steuerzeichen "neue Zeile"

DU
quelle
88
-1 Der OP ist mit der "\ n" Escape - Sequenz. Es funktioniert nicht, weil sie dem Backslash nicht als "\\ n" entkommen. Python konvertiert die Escape-Sequenz in ein Zeilenumbruchzeichen, anstatt sie buchstäblich als Backslash gefolgt von einem en zu belassen, wie es JSON erfordert.
user359996
6
@ user359996 Ich bin nicht sicher, ob das stimmt. Für mich (Daten in JSON mit just speichern \nund über Curses ausgeben) \nscheint das in Ordnung zu sein. Es hängt anscheinend von der Ansichts- / Rendering-Engine ab.
Asche999
2
Newline-Sequenzen sind in der Tat plattformspezifisch (vgl. En.wikipedia.org/wiki/Newline#Representations ). Gemäß @ Lightness Races in der Antwort von Orbit sind jedoch weder Cursor-Return- noch Zeilenvorschubzeichen in der JSON-Grammatik enthalten. Ich bin eigentlich kein Python-Programmierer, daher bin ich mir nicht sicher, was in Ihrem Fall vor sich geht, aber entweder ist Ihr Parser kaputt oder Sie übergeben ihn nicht so, wie Sie denken. Vielleicht erklärt diese Antwort es besser: stackoverflow.com/a/9295597/359996 . Beachten Sie insbesondere das bisschen über doppeltes Entkommen.
user359996
5
@Nawaz: "\ n" und "\ r" sind Escape-Sequenzen für Zeilenvorschub bzw. Wagenrücklauf. Sie sind nicht die wörtlichen und Zeilenvorschub Wagenrücklauf - Steuerzeichen . Beachten Sie als zusätzliches Beispiel, dass "\\" eine Escape-Sequenz für Backslash ist, im Gegensatz zu einem wörtlichen Backslash. Die JSON-Grammatik schließt Steuerzeichen explizit aus (vgl. Die "char" -Definition) und sorgt stattdessen für deren Darstellung über Escape-Sequenzen (\\, \ r, \ n usw.).
user359996
2
@ user359996: Ja. Ich habe das später gesehen, obwohl ich meinen alten Kommentar als solchen behalte, falls jemand anderes den gleichen Zweifel hat, könnte unsere Diskussion ihnen helfen. Danke, dass du es übrigens bestätigt hast.
Nawaz
197

Ich habe dies für ein kleines Node.js Projekt zu tun und fanden diese Behelfslösung :

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

 ],
}

Das sieht für mich ganz ordentlich aus, abgesehen davon muss ich überall doppelte Anführungszeichen verwenden. Ansonsten könnte ich vielleicht YAML verwenden, aber das hat andere Fallstricke und wird von Haus aus nicht unterstützt. Einmal analysiert, verwende ich einfach myData.modify_head.join('\n')oder myData.modify_head.join(), je nachdem, ob ich nach jedem String einen Zeilenumbruch möchte oder nicht.

Fehlerentwickler
quelle
40
Dies ist eine Lösung für eine bestimmte Einstellung, die nicht unbedingt mit der Frage zusammenhängt. Was Sie dort erstellen, sind keine mehrzeiligen Zeichenfolgen (was sowieso nicht möglich ist), sondern Arrays mit Zeichenfolgen im Inneren
Samuel Rivas
3
Dies zeigt, wie Zeilenumbrüche in Zeichenfolgen eingefügt werden, wodurch die Frage NICHT beantwortet wird. Diese Antwort tut es.
fgrieu
1
fgrieu - man könnte die Strings genauso einfach verketten, ohne eine neue Zeile hinzuzufügen. Mit dieser kleinen Änderung wird eine Problemumgehung für mehrzeilige Zeichenfolgen bereitgestellt (sofern Sie die Kontrolle über die Angabe des JSON-Schemas haben). Ich werde versuchen, die Antwort damit zu verbessern.
Drrob
1
Danke, das gefällt mir. Ich mache das für das, woran ich arbeite. Es sieht ordentlich und organisiert aus. Jede neue Zeile in diesem Array impliziert einen Zeilenumbruch im ausgegebenen Text, obwohl diese Lösung auch in Fällen funktionieren kann, in denen Sie keine Zeilenumbrüche einfügen. Ich habe diese Lösung bereits in meinem Javascript-Quellcode verwendet, nur weil mir gefallen hat, wie gut sie organisiert ist und wie sie keinen Zweifel daran lässt, welche Arten von Leerzeichen in die endgültige Zeichenfolge gelangen.
Gal
Ungeachtet der Vorbehalte des JSON-Erfinders habe ich dies nur verwendet, um Kommentare hinzuzufügen (ohne den Javascript-Teil, aber nur die [] und Kommas), um Kommentare hinzuzufügen, um einem möglichen zukünftigen Betreuer zu helfen, der meine kleine JSON-Datei möglicherweise von Hand bearbeitet.
Whirl Mind
116

Leider befassen sich viele der Antworten hier mit der Frage, wie ein Zeilenumbruchzeichen in die Zeichenfolgendaten eingefügt werden soll. Die Frage ist, wie der Code schöner aussehen kann, indem der Zeichenfolgenwert auf mehrere Codezeilen aufgeteilt wird. (Und selbst die Antworten, die dies erkennen, bieten "Lösungen", bei denen davon ausgegangen wird, dass man die Datendarstellung ändern kann, was in vielen Fällen nicht der Fall ist.)

Und die schlimmste Nachricht ist, dass es keine gute Antwort gibt.

In vielen Programmiersprachen können Sie die Zeichenfolgenverkettung verwenden, um den gewünschten Effekt zu erzielen, auch wenn sie das Aufteilen von Zeichenfolgen über Zeilen nicht explizit unterstützen. und solange der Compiler nicht schrecklich ist, ist das in Ordnung.

Aber json ist keine Programmiersprache; Es ist nur eine Datendarstellung. Sie können nicht festlegen, dass Zeichenfolgen verkettet werden sollen. Die (ziemlich kleine) Grammatik enthält auch keine Möglichkeit, eine Zeichenfolge in mehreren Zeilen darzustellen.

Ohne einen Vorprozessor zu entwickeln (und ich habe nicht das Gefühl, meine eigene Sprache effektiv zu erfinden, um dieses Problem zu lösen), gibt es keine allgemeine Lösung für dieses Problem. Wenn Sie das Datenformat ändern können, können Sie ein Array von Zeichenfolgen ersetzen. Andernfalls ist dies eine der zahlreichen Möglichkeiten, mit denen json nicht für die menschliche Lesbarkeit ausgelegt ist.

Mark Adelsberger
quelle
3
Es ist nicht klar, was das OP will, Zeilenumbrüche in Zeichenfolgen oder Zeichenfolgen besser organisieren ...
9ilsdx 9rvj 0lo
3
@ 9ilsdx9rvj0lo: Nein, das ist es nicht.
Mark Adelsberger
Zu "Die Frage ist, wie der Code durch Aufteilen des Zeichenfolgenwerts auf mehrere Codezeilen besser aussehen kann ...": Eine Lösung für mehrzeilige Anweisungen in Python finden Sie unter stackoverflow.com/questions/53162/… . Es gibt einen Unterschied zwischen mehrzeiligem JSON und mehrzeiligem Python. Mehrzeiliger JSON verwendet '\' gefolgt von 'n' im JSON, dh "\ n" in der Zeichenfolge. Bei mehrzeiligen Python-Anweisungen verwenden Sie '\' gefolgt von '\ n', dh einen abschließenden Backslash in der Zeile, die fortgesetzt werden soll. Windows-Format: Ersetzen Sie \ n gegebenenfalls durch \ r \ n!
Ivan
106

Überprüfen Sie die Spezifikation ! Die JSON Grammatik char Produktion kann die folgenden Werte annehmen:

  • any-Unicode-Zeichen- "außer- \oder-oder-Steuerzeichen
  • \"
  • \\
  • \/
  • \b
  • \f
  • \n
  • \r
  • \t
  • \u vier hexadezimale Ziffern

Zeilenumbrüche sind "Steuerzeichen". Nein, Sie haben möglicherweise keinen wörtlichen Zeilenumbruch in Ihrer Zeichenfolge. Sie können es jedoch mit einer beliebigen Kombination von \nund codieren \r.

Leichtigkeitsrennen im Orbit
quelle
3
Dies ist die richtige Antwort, da sie keine Mehrdeutigkeit hinterlässt. Neue Zeilen sind gemäß Spezifikation zulässig, sofern sie ordnungsgemäß mit dem Steuerzeichen maskiert sind.
Ryan
@AliKhaki \ n in JSON wird das von der Frage angestrebte Ergebnis nicht erreichen. Entweder denken Sie an etwas anderes (dh das Einbetten von Zeilenumbrüchen), oder Sie sprechen von einer neuen Zeile in einem Zeichenfolgenliteral (das JSON enthält) in einer Programmiersprache, was wiederum etwas anderes ist.
Leichtigkeitsrennen im Orbit
@ LightnessRacesinOrbit Ja, ich suche nach Newline in String
Ali Khaki
46

JSON erlaubt keine Zeilenumbrüche zur besseren Lesbarkeit.

Am besten verwenden Sie eine IDE, die den Zeilenumbruch für Sie übernimmt.

James Gentes
quelle
1
Ein Editor wie BBEdit, der "weichen" Zeilenumbruch unterstützt, ist ideal. Der Text wird so umbrochen, dass alles im sichtbaren Bereich des Editorfensters angezeigt wird. Beim Speichern bleiben jedoch nur die von Ihnen eingegebenen Zeilenenden (z. B. Wagenrücklauf) in der Datei erhalten. Erleichtert das Bearbeiten von JSON mit sehr langen Zeichenfolgen, ohne auf Codetricks oder Hacks zurückgreifen zu müssen.
Cshotton
44

Dies ist eine wirklich alte Frage, aber ich bin bei einer Suche darauf gestoßen und glaube, ich kenne die Ursache Ihres Problems.

JSON erlaubt keine "echten" Zeilenumbrüche in seinen Daten. es kann nur Zeilenumbrüchen entkommen sein. Siehe die Antwort von @YOU . Der Frage zufolge haben Sie in Python auf zwei Arten versucht, Zeilenumbrüche zu umgehen: mithilfe des Zeilenfortsetzungszeichens ( "\") oder "\n"als Escapezeichen.

Beachten Sie jedoch: Wenn Sie eine Zeichenfolge in Python verwenden, werden Sonderzeichen ( "\t", "\n") in REAL-Steuerzeichen übersetzt! Das "\n"wird durch das ASCII-Steuerzeichen ersetzt, das ein Zeilenumbruchzeichen darstellt. Dies ist genau das Zeichen, das in JSON unzulässig ist. (Das Zeilenfortsetzungszeichen nimmt einfach die neue Zeile heraus.)

Sie müssen also verhindern, dass Python Zeichen entkommt. Sie können dies tun, indem Sie eine rohe Zeichenfolge verwenden (wie rin vor die Zeichenfolge setzen r"abc\ndef"oder einen zusätzlichen Schrägstrich vor die neue Zeile einfügen ( "abc\\ndef").

Beide oben "\n"genannten Zeichen werden nicht durch das echte ASCII-Steuerzeichen für Zeilenumbrüche ersetzt, sondern "\n"als zwei Literalzeichen, die JSON dann als Zeilenumbruch interpretieren kann.

Kaum bekannt
quelle
12

Schreiben Sie den Eigenschaftswert als Array von Zeichenfolgen. Wie hier angegebenes Beispiel https://gun.io/blog/multi-line-strings-in-json/ . Das wird helfen.

Wir können immer ein Array von Zeichenfolgen für mehrzeilige Zeichenfolgen wie die folgenden verwenden.

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

Und wir können das Array leicht iterieren, um Inhalte mehrzeilig anzuzeigen.

Sandip Nirmal
quelle
1
Ich würde vorschlagen, dass Sie die Informationen in Ihrer Antwort über den Link hinzufügen, da Links in Zukunft unterbrochen werden können.
YoungHobbit
5
Aber sie haben ein Array, keine Zeichenfolge. Ein Array ist keine Zeichenfolge. Zeitraum.
9ilsdx 9rvj 0lo
Ich habe nur daran gedacht. Nett!
Phillip Jacobs
12

Verwenden Sie json5 (Loader), siehe https://json5.org/ - Beispiel (von json5)

{
  lineBreaks: "Look, Mom! \
No \\n's!",
}
Lacom
quelle
Die Frage, die das OP gestellt hat. Zumindest wenn er json5 benutzen kann.
Nomen
10

Ist es möglich, mehrzeilige Zeichenfolgen in JSON zu haben?

Ja. Ich habe dies jetzt mit meinem Firefox-Webbrowser getestet, indem ich F12 gedrückt, auf Konsole geklickt und am unteren Bildschirmrand eingegeben habe.

x={text:"hello\nworld"}

Objekt x wurde gerade aus einer Zeichenfolge im JSON-Format erstellt, die eine mehrzeilige Zeichenfolge enthält.

console.log(x.text)
hello
world

x.text wird angezeigt und zeigt an, dass es sich um eine mehrzeilige Zeichenfolge handelt.

Diese beiden Tests zeigen, dass der Javascript-Interpreter von Firefox gerne JSON mit mehrzeiligen Zeichenfolgen erstellt und verwendet.

Weitere Tests mit JSON.stringifyund JSON.parsezeigten, dass der Javascript-Interpreter ein Objekt mit mehrzeiligen Zeichenfolgen in JSON konvertieren und problemlos wieder analysieren kann.

Ich habe in der Vergangenheit die gesamten Werke von Shakespeare als Eigentum in einem JSON-Objekt gespeichert und sie dann unverfälscht über das Internet gesendet.

Beispiel

Hier ist eine zweizeilige Zeichenfolge, die über drei Zeilen eingegeben wird

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

Wir können das Objekt anzeigen

console.log(x)

geben

Object { text: "experts\nexchange" }

oder die Zeichenfolge

console.log(x.text)

geben

experts
exchange

Das Zeilenende in der Zeichenfolge ergibt sich aus der Verwendung von \ n, und die mehreren Eingabezeilen werden mit nur \ am Zeilenende erreicht.

In der Praxis möchten Sie möglicherweise Ihre Zeilenenden mit denen in der Zeichenfolge synchronisieren, z

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

Mehrzeilige Stringlänge

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

Beachten Sie, dass die Zeichenfolge mit dem Zeilenumbruch nicht länger ist als die Zeichenfolge mit dem Leerzeichen. Obwohl zwei Zeichen auf der Tastatur eingegeben wurden ('\' und 'n'), wird nur ein Zeichen in der Zeichenfolge gespeichert.

Ivan
quelle
3
Ein JavaScript-String-Format-Reader ist kein JSON-String-Format-Reader und umgekehrt. Während dies funktioniert, akzeptiert die JavaScript-Konsole auch x={"a":NaN}und x={"a":"a \<literal newline with SHIFT>b"}, die nicht JSON sind, sondern JavaScript
cat
9

Verwenden Sie Regex, um alle Vorkommen von \r\ndurch zu ersetzen \\n.

Das hat bei mir in Scala funktioniert.

val newstr = str.replace("\r\n", "\\n")
Sikander
quelle
Warum die 3 Backslashes?
neXus
6
@neXus Ich weiß nicht warum, aber jemand hatte es auf 3 Backslashes bearbeitet. Vielen Dank an LightnessRacesInOrbit für die Korrektur.
Sikander
5

Wenn Sie bereit sind, Node.js zu verwenden, können Sie dies tun:

module.exports = {

  multilineStr: `

     dis my life 
     it's now or never

  `

}

Sie können mit Node.js importieren und es einfach wie folgt in JSON konvertieren:

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

und du bekommst:

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

So funktioniert es : Sie verwenden Node.js, um ein JS-Modul zu laden, das ein JS-Objekt erstellt, das von Node.js leicht mit JSON-Zeichenfolgen versehen werden kann. Die Option -e wertet die Zeichenfolge aus, und die -pOption gibt das Rückgabeergebnis der letzten Node.js-Operation an stdout wieder.

Wenn Sie ein .js-Skript laden möchten, das sich in einem anderen Arbeitsverzeichnis befindet, müssen Sie die Zeichenfolgen "" und '' wechseln:

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

Versuchen Sie es mit einem base64codierten Zeichenfolgenwert. Hat die meiste Zeit für mich gearbeitet.

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

nach base64codierten Zeichenfolge aussehen wie

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

Die Base64-Codierung und -Decodierung ist in allen Sprachen verfügbar.

Sunit Parekh
quelle
7
Sie benötigen speziellen Code, um ihn anzuzeigen. Sie wandeln eine Zeichenfolge in ein Array um. Es ist keine Lösung
tom10271
3
Ich denke, dies ist eine schlechte Idee - sie verschleiert den Inhalt unnötig und erfordert zusätzlichen Code, Zeit, Speicher und Werkzeuge, um ihn zu produzieren und zu konsumieren. Das Durchsuchen der Zeichenfolge und das Ersetzen von Sonderzeichen erfordert natürlich auch zusätzlichen Code, Zeit und Speicher, aber definitiv weniger als die Base64-Codierung und -Decodierung
Semanino
Dies ist eine schlechte Idee, da die Lesbarkeit des JSON nicht mehr gewährleistet ist und Sie, wie bereits bei @ tom10271 erwähnt, zusätzliche Operationen benötigen, um den json
T90
-23

Setzen Sie den mehrzeiligen Text in die TXT-Datei und dann

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

(es funktioniert auf mongoDB)

Flaalf
quelle
11
-1: Dies ist eine irreführende Antwort. Es ist weder gültiges JSON noch funktioniert es in Javascript, da keine Funktion benannt ist cat.
Martin Schuhfuß