Ciągi wielowierszowe w JSON


655

Piszę niektóre pliki danych w formacie JSON i chciałbym, aby niektóre naprawdę długie wartości ciągu były podzielone na wiele wierszy. Używając modułu JSON Pythona, otrzymuję wiele błędów, niezależnie od tego, czy używam, \czy \njako ucieczki.

Czy w JSON jest możliwe ciągi wieloliniowe? To głównie dla wygody wizualnej, więc przypuszczam, że mogę po prostu włączyć zawijanie wyrazów w moim edytorze, ale jestem trochę ciekawy ...



1
uporządkuj swoje dane: podziel łańcuch wielowierszowy na tablicę ciągów, a następnie dołącz je później.
RubyT TuesdayDONO

2
Wypróbuj narzędzie hjson. Przekształci Twój ciąg multilinii w json do odpowiedniego formatu json.
gaurav

Odpowiedzi:


401

JSON nie pozwala na prawdziwe łamanie linii. Musisz zastąpić wszystkie podziały linii \n.

na przykład:

"first line second line"

można zapisać za pomocą:

"first line\nsecond line"

Uwaga:

ponieważ Pythonnależy to zapisać jako:

"first line\\nsecond line"

gdzie \\jest ucieczka przed odwrotnym ukośnikiem, w przeciwnym razie python będzie traktował \njako znak kontrolny „nowy wiersz”


88
-1 PO jest za pomocą „n \” sekwencja ucieczki. To nie działa, ponieważ nie unikają odwrotnego ukośnika , jak „\\ n”, więc Python konwertuje sekwencję zmiany znaczenia na znak nowej linii, zamiast pozostawiać ją dosłownie jako odwrotny ukośnik, po której następuje en, zgodnie z wymaganiami JSON.
user359996,

6
@ user359996 Nie jestem pewien, czy to prawda. Dla mnie (przechowywanie danych w JSON \n-ie za pomocą just i wysyłanie ich przez Curses) \nwydaje się działać dobrze. Wygląda na to, że zależy to od silnika wyświetlania / renderowania.
ashes999

2
Sekwencje nowego wiersza są rzeczywiście specyficzne dla platformy (por. En.wikipedia.org/wiki/Newline#Representations ). Jednak według @Lightness Races w odpowiedzi Orbity ani znaki powrotu kursora, ani przesunięcia wiersza nie znajdują się w gramatyce JSON. Właściwie nie jestem programistą Python, więc nie jestem pewien, co się dzieje w twoim przypadku, ale albo twój parser jest zepsuty, albo nie przekazujesz tego, co myślisz, że jesteś. Być może ta odpowiedź wyjaśnia to lepiej: stackoverflow.com/a/9295597/359996 . Zwróć uwagę zwłaszcza na podwójne ucieczki.
user359996,

5
@Nawaz: „\ n” i „\ r” są sekwencjami ucieczki odpowiednio dla wysuwu linii i powrotu karetki. Nie są to dosłowne znaki kontrolne przesuwu linii i powrotu karetki . Jako dodatkowy przykład dla wyjaśnienia, rozważmy, że „\\” jest sekwencją ucieczki dla odwrotnego ukośnika, w przeciwieństwie do dosłownego odwrotnego ukośnika. Gramatyka JSON wyraźnie wyklucza znaki kontrolne (por. Definicja „char”), a zamiast tego zapewnia ich reprezentację za pomocą sekwencji specjalnych (\\, \ r, \ n itd.).
user359996,

2
@ user359996: Tak .. Widziałem to później, chociaż zachowuję swój stary komentarz jako taki, na wypadek gdyby ktoś miał podobne wątpliwości, nasza dyskusja może im pomóc. dzięki za potwierdzenie BTW.
Nawaz

197

Musiałem to zrobić dla małego projektu Node.js i znalazłem obejście :

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

 ],
}

Wydaje mi się to całkiem fajne, poza tym muszę wszędzie używać podwójnych cudzysłowów. Chociaż w przeciwnym razie mógłbym użyć YAML, ale ma to inne pułapki i nie jest obsługiwane natywnie. Po przeanalizowaniu po prostu używam myData.modify_head.join('\n')lub myData.modify_head.join(), w zależności od tego, czy chcę łamać linie po każdym łańcuchu, czy nie.


40
Jest to rozwiązanie dla konkretnego ustawienia, niekoniecznie związane z pytaniem. To, co tworzysz, nie ma łańcuchów wielowierszowych (co i tak nie jest możliwe), ale tablice z łańcuchami w środku
Samuel Rivas

3
To pokazuje, jak wstawić znak nowej linii w ciągach, co NIE odpowiada na pytanie. Ta odpowiedź brzmi .
fgrieu

1
fgrieu - równie łatwo można połączyć łańcuchy bez dodawania nowej linii. Ta niewielka zmiana zapewnia obejście ciągów wielowierszowych (o ile masz kontrolę nad specyfikacją schematu JSON). Spróbuję poprawić odpowiedź dzięki temu.
drrob

1
Dzięki, podoba mi się to. Idę z tym nad tym, nad czym pracuję. Wygląda schludnie i uporządkowany. Chcę, aby każdy nowy wiersz w tej tablicy oznaczał podział wiersza w wyprowadzanym tekście, chociaż to rozwiązanie może również działać w przypadkach, w których nie wstawisz podziałów wiersza. Użyłem tego rozwiązania wcześniej w kodzie źródłowym javascript tylko dlatego, że podobało mi się to, jak jest uporządkowany i jak nie pozostawia wątpliwości co do tego, jakie białe znaki wstawiają się do końcowego ciągu.
Gal

Pomimo zastrzeżeń wynalazcy JSON, użyłem tego tylko do dodania komentarzy (bez części javascript, ale tylko [] i przecinków), aby dodać komentarze, aby pomóc potencjalnemu opiekunowi, który mógłby ręcznie edytować mój mały plik JSON.
Whirl Mind

116

Niestety wiele odpowiedzi tutaj dotyczy pytania, jak wstawić znak nowej linii w danych ciągu. Pytanie brzmi, jak poprawić wygląd kodu, dzieląc wartość ciągu na wiele wierszy kodu. (I nawet odpowiedzi, które to rozpoznają, zapewniają „rozwiązania”, które zakładają, że można dowolnie zmieniać reprezentację danych, co w wielu przypadkach nie jest).

A najgorsze jest to, że nie ma dobrej odpowiedzi.

W wielu językach programowania, nawet jeśli nie obsługują one jawnie podziału ciągów między wierszami, nadal można użyć konkatenacji ciągów, aby uzyskać pożądany efekt; i dopóki kompilator nie jest okropny, nie ma problemu.

Ale json nie jest językiem programowania; to tylko reprezentacja danych. Nie możesz tego powiedzieć, żeby łączyć łańcuchy. Jego (dość mała) gramatyka nie obejmuje również żadnej funkcji do reprezentowania łańcucha na wielu liniach.

Pomijając opracowanie jakiegoś preprocesora (a ja, na przykład, nie mam ochoty skutecznie wymyślić własnego języka, aby rozwiązać ten problem), nie ma ogólnego rozwiązania tego problemu. JEŚLI możesz zmienić format danych, możesz zastąpić tablicę ciągów. W przeciwnym razie jest to jeden z wielu sposobów, w jakie Json nie jest zaprojektowany z myślą o czytelności dla ludzi.


3
Nie jest jasne, czego chce OP, nowe wiersze w łańcuchu ani lepiej organizować ciąg ...
9ilsdx 9rvj 0lo

3
@ 9ilsdx9rvj0lo: Nie, nie jest.
Mark Adelsberger

Jeśli chodzi o „Pytanie brzmi, jak zrobić ładniejszy wygląd kodu przez podzielenie wartości ciągu w wielu linii kodu ...”: do rozwiązania sprawozdania multi-line w Pythonie, zobacz stackoverflow.com/questions/53162/... . Istnieje różnica między wieloliniowym JSON a wieloliniowym Pythonem. Wielowierszowy JSON używa „\”, po którym następuje „n” w JSON, tj. „\ N” w ciągu. Wielowierszowe instrukcje Pythona, użyj „\”, a następnie „\ n”, tj. Końcowego ukośnika odwrotnego w linii, która ma być kontynuowana. Format Windows: w razie potrzeby zamień \ n na \ r \ n!
Ivan

106

Sprawdź specyfikację ! JSON gramatyki za char produkcja może przyjmować następujące wartości:

  • dowolny-znak-Unicode-z wyjątkiem "-lub \-lub-kontrolny
  • \"
  • \\
  • \/
  • \b
  • \f
  • \n
  • \r
  • \t
  • \u czterocyfrowe cyfry

Nowe linie to „znaki kontrolne”, więc nie, możesz nie mieć dosłownie nowej linii w swoim ciągu. Można go jednak zakodować, używając dowolnej kombinacji \ni \rwymaganej.



3
To poprawna odpowiedź, ponieważ nie pozostawia dwuznaczności. Nowe wiersze dozwolone, zgodnie ze specyfikacją, pod warunkiem, że są one odpowiednio oznaczone znakiem kontrolnym.
Ryan

@AliKhaki \ n w JSON nie osiągnie wyniku poszukiwanego przez pytanie. Albo myślisz o czymś innym (np. Osadzanie znaków nowej linii), albo mówisz o nowej linii w dosłownym łańcuchu znaków (zawierającym JSON) w jakimś języku programowania, co znowu jest czymś innym.
Wyścigi lekkości na orbicie

@LightnessRacesinOrbit tak, szukam nowej linii w ciągu
Ali Khaki,

46

JSON nie zezwala na przerywanie linii dla czytelności.

Najlepszym rozwiązaniem jest skorzystanie z IDE, które zawinie dla Ciebie.


1
Idealny jest edytor taki jak BBEdit, który obsługuje „miękkie” zawijanie linii. Zawija tekst, tak aby wszystko pojawiało się w widocznym obszarze okna edytora, ale tylko wpisywane przez ciebie zakończenia linii (np. Naciśnięcie klawisza return) są zachowywane w pliku podczas zapisywania. Ułatwia edycję JSON z naprawdę długimi łańcuchami bez konieczności uciekania się do sztuczek kodowych lub hacków.
cshotton

44

To naprawdę stare pytanie, ale natknąłem się na to podczas wyszukiwania i myślę, że znam źródło twojego problemu.

JSON nie zezwala na „prawdziwe” znaki nowej linii w swoich danych; mógł jedynie uciec od nowych linii. Zobacz odpowiedź z @YOU . Zgodnie z pytaniem wygląda na to, że próbowałeś uciec przed łamaniem linii w Pythonie na dwa sposoby: używając znaku kontynuacji linii ( "\") lub używając "\n"znaku ucieczki.

Pamiętaj jednak: jeśli używasz ciągu znaków w pythonie, specjalne znaki specjalne ( "\t", "\n") są tłumaczone na PRAWDZIWE znaki sterujące! The"\n"Zostaną zastąpione znakiem kontrolnym ASCII reprezentujący znak nowej linii, która jest właśnie znak, że jest nielegalne w JSON. (Jeśli chodzi o znak kontynuacji linii, po prostu usuwa on nową linię).

Musisz więc zapobiec ucieczce znaków w Pythonie. Możesz to zrobić, używając nieprzetworzonego ciągu (umieszczonego rprzed ciągiem, jak w r"abc\ndef", lub dodając dodatkowy ukośnik przed znakiem nowej linii ( "abc\\ndef").

Oba powyższe zamiast zastąpić "\n"prawdziwym znakiem kontrolnym ASCII nowej linii, pozostaną "\n"jako dwa dosłowne znaki, które następnie JSON może interpretować jako znak nowej linii.


12

Zapisz wartość właściwości jako tablicę ciągów. Jak przykład podany tutaj https://gun.io/blog/multi-line-strings-in-json/ . To pomoże.

Zawsze możemy użyć tablicy ciągów dla ciągów wielowierszowych, takich jak następujące.

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

I możemy z łatwością iterować tablicę, aby wyświetlać zawartość w sposób wieloliniowy.


1
Sugerowałbym dodanie informacji w odpowiedzi z linku, ponieważ linki mogą się zepsuć w przyszłości.
YoungHobbit,

5
Ale masz tablicę, a nie ciąg. Tablica nie jest łańcuchem. Kropka.
9ilsdx 9rvj 0lo

Właśnie o tym myślałem. Miły!
Phillip Jacobs

12

Użyj json5 (moduł ładujący) patrz https://json5.org/ - przykład (autor: json5)

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

Pytanie zadane przez OP. Przynajmniej jeśli może użyć json5.
nomen

10

Czy w JSON jest możliwe ciągi wieloliniowe?

Tak. Właśnie przetestowałem to teraz w przeglądarce Firefox, naciskając klawisz F12, klikając konsolę i pisząc u dołu ekranu.

x={text:"hello\nworld"}

Obiekt x został właśnie utworzony z ciągu formatu JSON zawierającego ciąg wielu wierszy.

console.log(x.text)
hello
world

Wyświetlany jest x. tekst pokazujący, że jest to ciąg wieloliniowy.

Te dwa testy pokazują, że interpreter JavaScript Firefoksa chętnie tworzy i używa JSON z ciągami wielowierszowymi.

Więcej testów z JSON.stringifyi JSON.parsepokazało, że interpreter Javascript może konwertować obiekt zawierający wielowierszowe łańcuchy do JSON i parsować go ponownie bez żadnego problemu.

W przeszłości przechowywałem pełne dzieła Szekspira jako właściwość w obiekcie JSON, a następnie przesyłałem je przez Internet, bez szwanku.

Przykład

Oto ciąg dwóch linii wprowadzony przez trzy linie

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

Możemy wyświetlić obiekt

console.log(x)

dający

Object { text: "experts\nexchange" }

lub ciąg

console.log(x.text)

dający

experts
exchange

Koniec linii w łańcuchu wynika z użycia \ n, a wiele linii wejściowych jest uzyskiwanych za pomocą \ tylko na końcu linii.

W praktyce możesz zsynchronizować zakończenia linii z zakończeniami w łańcuchu, np

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

Długość sznurka wieloliniowego

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

Zauważ, że ciąg z nową linią nie jest dłuższy niż ciąg ze spacją. Mimo że na klawiaturze wpisano dwa znaki („\” i „n”), w ciągu jest przechowywany tylko jeden znak.


3
Czytnik formatu ciągów JavaScript nie jest czytnikiem formatu ciągów JSON i odwrotnie, więc chociaż działa, konsola JavaScript również akceptuje x={"a":NaN}i x={"a":"a \<literal newline with SHIFT>b"}, które nie są JSON, ale są JavaScript
cat

9

Użyj regex, aby zastąpić wszystkie wystąpienia \r\nz \\n.

To działało dla mnie w scala.

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

Dlaczego 3 ukośniki odwrotne?
neXus

6
@neXus Nie wiem dlaczego, ale ktoś edytował go do 3 ukośników odwrotnych. Dzięki LightnessRacesInOrbit za poprawienie tego.
Sikander,

5

Jeśli chcesz korzystać z Node.js, możesz to zrobić:

module.exports = {

  multilineStr: `

     dis my life 
     it's now or never

  `

}

możesz zaimportować za pomocą Node.js i łatwo przekonwertować go na JSON:

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

i dostajesz:

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

jak to działa : używasz Node.js, aby załadować moduł JS, który tworzy obiekt JS, który można łatwo łączyć w JSON przez Node.js. Opcja -e ocenia ciąg znaków, a -popcja echa zwraca wynik ostatniej operacji Node.js na standardowe wyjście.

Jeśli chcesz załadować skrypt .js, który znajduje się w innym katalogu roboczym, musisz przełączyć ciągi „” i „”:

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

-4

Spróbuj użyć base64zakodowanej wartości ciągu. Pracował dla mnie przez większość czasu.

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

po base64zakodowanym ciągu wygląda

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

Kodowanie i dekodowanie base64 jest dostępne we wszystkich językach.


7
Potrzebujesz specjalnego kodu, aby go wyświetlić, transformujesz ciąg znaków w tablicę. To nie jest rozwiązanie
tom10271

3
Myślę, że to zły pomysł - niepotrzebnie zaciemnia treść i wymaga dodatkowego kodu, czasu, pamięci oraz narzędzi do jej wytworzenia i zużycia. Skanowanie za pomocą sznurka i zastępując znaki specjalne oczywiście wymaga dodatkowego kodu, czas i pamięć też, ale zdecydowanie mniej niż base64 kodowania i dekodowania
Semanino

Jest to zły pomysł, ponieważ nie ma czytelności JSON, a także, jak wspomniano @ tom10271, potrzebujesz dodatkowej operacji, aby użyć json
T90

-23

umieść tekst wielowierszowy w pliku txt, a następnie

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

(działa na mongoDB)


11
-1: jest to myląca odpowiedź. To nie jest poprawny JSON ani nie działa w javascript, ponieważ nie ma nazwanej funkcji cat.
Martin Schuhfuß
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.