Багаторядкові рядки в JSON


655

Я пишу деякі файли даних у форматі JSON, і хотілося б, щоб деякі дійсно довгі рядкові значення були розділені на кілька рядків. Використовуючи модуль JSON python, я отримую велику кількість помилок, будь то я, \або \nяк вихід.

Чи можливо мати багаторядкові рядки в JSON? Це здебільшого для візуального комфорту, тому я гадаю, що я можу просто ввімкнути обговорення слів у своєму редакторі, але мені просто цікаво ...



1
Структуруйте свої дані: розбийте багаторядковий рядок на масив рядків, а потім приєднайтеся до них згодом.
RubyTuesdayDONO

2
Спробуйте інструмент hjson. Він перетворить ваш багаторядковий рядок у json у правильний формат json.
gaurav

Відповіді:


401

JSON не допускає реальних розривів ліній. Потрібно замінити всі перерви рядка на \n.

наприклад:

"first line second line"

можна зберегти за допомогою:

"first line\nsecond line"

Примітка:

бо Pythonце слід писати так:

"first line\\nsecond line"

де \\для уникнення зворотної косої риси, інакше python буде розглядатись \nяк контрольний символ "нова лінія"


88
-1 ОП в використанні «\ N» послідовності. Це не працює, тому що вони не уникають зворотної косої риси , як "\\ n", тому Python перетворює послідовність вхідного символу в символ нового рядка, а не залишає його як буквально зворотну косу рису, що супроводжується en, як вимагає JSON.
користувач359996

6
@ user359996 Я не впевнений, що це правда. Для мене (зберігання даних у JSON за допомогою справедливих \nта виведення їх через Curses), \nздається, працює нормально. Це залежить від двигуна перегляду / візуалізації, здається.
ashes999

2
Послідовності нового рядка дійсно залежать від платформи (див. En.wikipedia.org/wiki/Newline#Representations ). Однак у відповідях на @Lightness Races у відповіді Орбіти, ні символи повернення курсору, ні символи подачі рядків не містяться в граматиці JSON. Я насправді не програміст Python, тому я не впевнений, що відбувається у вашому випадку, але або ваш аналізатор зламаний, або ви не передаєте йому те, що ви думаєте своїм. Можливо, ця відповідь пояснює це краще: stackoverflow.com/a/9295597/359996 . Зверніть увагу особливо на подвійне втечу.
користувач359996

5
@Nawaz: "\ n" і "\ r" - це послідовності аварійного виклику для передачі ліній та перевезення відповідно. Вони не буквені символи передачі ліній та перевезення-повернення . В якості додаткового прикладу, щоб зробити це більш зрозумілим, розглянемо, що "\\" є послідовністю відхилення для зворотної косої риси, на відміну від прямої косої риски. Граматика JSON явно виключає символи керування (пор. Визначення "char"), а натомість передбачає їх представлення за допомогою послідовностей втечі (\\, \ r, \ n тощо).
користувач359996

2
@ user359996: Так .. Я це бачив пізніше, хоча я зберігаю свій старий коментар як такий, якщо хтось інший зіткнеться з тим же сумнівом, наше обговорення може їм допомогти. дякую за підтвердження.
Наваз

197

Мені довелося це зробити для невеликого проекту Node.js і знайшов цю роботу :

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

 ],
}

Для мене це виглядає досить акуратно, але, зважаючи на те, що я повинен використовувати подвійні лапки всюди. Хоча в іншому випадку я, можливо, міг би використовувати YAML, але він має інші підводні камені і не підтримується на самому початку. Після розбору я просто використовую myData.modify_head.join('\n')або myData.modify_head.join(), залежно від того, хочу я розрив рядка після кожного рядка чи ні.


40
Це рішення конкретної установки, не обов'язково пов'язане з питанням. Що ви там створюєте, це не багаторядкові рядки (що все одно неможливо), а масиви з рядками всередині
Самуель Рівас

3
Це показує, як вставити новий рядок у рядки, що НЕ відповідає на запитання. Ця відповідь так і є.
fgrieu

1
fgrieu - можна так само легко об'єднати рядки, не додавши новий рядок. Завдяки такій невеликій зміні він дозволяє вирішити багаторядкові рядки (якщо ви керуєте вказівкою схеми JSON). Я спробую покращити відповідь цим.
drrob

1
Спасибі, мені це подобається. Я йду з цим заради того, над чим працюю. Це виглядає акуратно і організовано. Я буду мати кожен новий рядок у цьому масиві, маючи на увазі розрив рядка у виведеному тексті, хоча це рішення може також працювати у випадках, коли ви не вставляєте розриви рядків. Я раніше використовував це рішення у своєму вихідному коді JavaScript лише тому, що мені сподобалось, як воно виглядає організовано і як це не залишає сумнівів щодо того, які види пробілів потрапляють у заключну рядок.
Гал

Незважаючи на застереження винахідника JSON, я просто використав це для додавання коментарів (без частини JavaScript, а лише [] та коми), щоб додати коментарі, щоб допомогти майбутньому технічному обслуговувачу, який міг би відредагувати мій маленький файл JSON.
Whirl Mind

117

На жаль, багато відповідей тут стосуються питання, як вписати символ рядка в рядкові дані. Питання полягає в тому, як зробити код виглядати приємніше, розділивши значення рядка на кілька рядків коду. (І навіть відповіді, які визнають це, дають "рішення", які передбачають, що вільне змінювати представлення даних, що у багатьох випадках - ні.)

І що гірша новина - хорошої відповіді немає.

У багатьох мовах програмування, навіть якщо вони явно не підтримують розбиття рядків по рядках, ви все одно можете використовувати конкатенацію рядків, щоб отримати бажаний ефект; і поки компілятор не жахливий, це добре.

Але json - це не мова програмування; це просто представлення даних. Ви не можете сказати це, щоб об'єднати рядки. Також граматика (досить невелика) не включає будь-який інструмент для подання рядка в декількох рядках.

Окрім розробки певного попереднього процесора (і, наприклад, я не відчуваю ефективності складання власної мови для вирішення цього питання), загального рішення цієї проблеми немає. Якщо ви можете змінити формат даних, то ви можете замінити масив рядків. В іншому випадку це один із численних способів того, що json не розроблений для читабельності людини.


3
Не ясно, чого хоче ОП, нові рядки в рядку чи краще організувати рядок ...
9ilsdx 9rvj 0lo

3
@ 9ilsdx9rvj0lo: Ні, це не так.
Марк Адельсбергер

Щодо "Питання полягає в тому, як зробити код виглядати приємніше, розділивши значення рядка на кілька рядків коду ...": для рішення багаторядкових операторів у Python див. Stackoverflow.com/questions/53162/… . Існує різниця між багаторядковим JSON і багаторядковим Python. Багаторядковий JSON використовує '\', а далі 'n' у JSON, тобто "\ n" у рядку. У багаторядкових операторах Python використовуйте '\', а потім '\ n', тобто зворотну косу рису на лінії, яку слід продовжити. Формат Windows: замініть \ n на \ r \ n, де це доречно!
Іван

106

Перевірте специфікацію ! У JSON граматики голець виробництва може набувати таких значень:

  • будь-який-Unicode-символ, за винятком- "або- \або-контроль-символ
  • \"
  • \\
  • \/
  • \b
  • \f
  • \n
  • \r
  • \t
  • \u чотиризначні цифри

Нові рядки є "контрольними символами", тому ні, можливо, у вашому рядку не буде буквального нового рядка. Однак ви можете кодувати його, використовуючи будь-яку комбінацію \nі \rвам потрібно.



3
Це правильна відповідь, оскільки не залишає двозначності. Нові лінії будуть дозволені, таким чином, щоб за умови , що вони належним чином врятувався з характером управління.
Райан

@AliKhaki \ n в JSON не досягне результату, який шукає питання. Або ви думаєте про щось інше (тобто вбудовування символів нового рядка), або ви говорите про новий рядок у рядковому літералі (що містить JSON) якоюсь мовою програмування, що знову щось інше.
Гонки легкості на орбіті

@LightnessRacesinOrbit так, я шукаю новий рядок у рядку
Алі Хакі

46

JSON не дозволяє переривати рядки для читабельності.

Ваша найкраща ставка - використовувати IDE, який буде завершено для вас.


1
Такий редактор, як BBEdit, який підтримує "м'яку" обертання ліній. Він обертає текст, щоб він відображався у видимій області вікна редактора, але у файлі зберігаються лише закінчення рядка, які ви вводите (наприклад, натискання на повернення каретки). Полегшує редагування JSON дійсно довгими рядками, не вдаючись до кодових хитрощів або хак.
cshotton

44

Це справді давнє питання, але я натрапив на це під час пошуку і, думаю, знаю джерело вашої проблеми.

JSON не допускає "реальних" нових рядків у своїх даних; вона могла лише уникнути нових рядків. Дивіться відповідь від @YOU . Згідно із запитанням, схоже, ви намагалися уникнути розривів рядків у Python двома способами: за допомогою символу продовження рядка ( "\") або за допомогою "\n"втечі.

Але майте на увазі: якщо ви використовуєте рядок у python, спеціальні символи "\t", що "\n"увійшли ( , ), переводяться у реальні контрольні символи! Заповіт "\n"буде замінено символом управління ASCII, що представляє символ нового рядка, який є саме символом, який є незаконним у JSON. (Що стосується символу продовження рядка, він просто виводить новий рядок.)

Отже, що вам потрібно зробити, це не допустити, щоб Python не вийшов з символів. Це можна зробити, використовуючи необроблений рядок (поставлений rперед рядком, як в r"abc\ndef", або додавши додаткову косу рису навпроти нового рядка ( "abc\\ndef").

Обидва вищевикладені замість заміни "\n"реального символу управління ASCII для нового рядка залишать "\n"як два прямолінійні символи, які потім JSON може інтерпретувати як вихід у новий рядок.


12

Запишіть значення властивості як масив рядків. Як приклад, наведений тут https://gun.io/blog/multi-line-strings-in-json/ . Це допоможе.

Ми завжди можемо використовувати масив рядків для багаторядкових рядків, як нижче.

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

І ми можемо легко ітератувати масив для відображення вмісту в багаторядковому режимі.


1
Я б запропонував вам додати інформацію у свою відповідь за посиланням, оскільки в майбутньому посилання можуть розірватися.
YoungHobbit

5
Але у них у вас є масив, а не рядок. Масив - це не рядок. Період.
9ilsdx 9rvj 0lo

Просто думав про це. Приємно!
Філіп Джейкобс

12

Використовуйте json5 (завантажувач) див. Https://json5.org/ - приклад (автор json5)

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

Питання, яке задав ОП. Принаймні, якщо він може використовувати json5.
номен

10

Чи можливо мати багаторядкові рядки в JSON?

Так. Я просто перевірив це зараз у своєму веб-переглядачі Firefox, натиснувши F12, клацнувши консоль і ввівши внизу екрана.

x={text:"hello\nworld"}

Об'єкт x щойно створений із рядка формату JSON, що містить багаторядковий рядок.

console.log(x.text)
hello
world

відображається x.text, що показує, що це багаторядковий рядок.

Ці два тести показують, що інтерпретатор Javascript Firefox із задоволенням створює та використовує JSON з багаторядковими рядками.

Більше тестів з JSON.stringifyі JSON.parseпоказав, що інтерпретатор Javascript може перетворити об’єкт, що містить багаторядкові рядки, в JSON і знову проаналізувати його знову, без проблем.

У минулому я зберігав цілі твори Шекспіра як власність в об'єкті JSON, а потім надсилав їх через Інтернет без пошкоджень.

Приклад

Ось дворядковий рядок, введений у три рядки

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

Ми можемо відобразити об’єкт

console.log(x)

давання

Object { text: "experts\nexchange" }

або рядок

console.log(x.text)

давання

experts
exchange

Кінець рядків у рядку є результатом використання \ n, а кілька вхідних рядків досягаються за допомогою просто \ в кінці рядка.

На практиці ви, можливо, захочете синхронізувати закінчення рядків з тими, що містяться в рядку, наприклад

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

Довжина рядкових рядків

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

Зауважте, що рядок з новим рядком не довший, ніж рядок з пробілом. Незважаючи на те, що на клавіатурі було введено два символи ('\' та 'n'), у рядку зберігається лише один символ.


3
Зчитувач формату рядків JavaScript не є зчитувачем формату рядків формату JSON, і навпаки, тому, хоча це трапляється, консоль JavaScript також приймає x={"a":NaN}і x={"a":"a \<literal newline with SHIFT>b"}, які не є JSON, але є JavaScript
кіт

9

Використовувати регулярний вираз для заміни всіх входжень \r\nз \\n.

Це працювало на мене в масштабі.

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

Чому 3 зворотні риски?
neXus

6
@neXus Я не знаю, чому, але хтось відредагував це на 3 зворотні риски. Завдяки LightnessRacesInOrbit за їх виправлення.
Сікандер

5

Якщо ви готові використовувати Node.js, ви можете зробити це:

module.exports = {

  multilineStr: `

     dis my life 
     it's now or never

  `

}

ви можете імпортувати за допомогою Node.js і легко перетворити його в JSON так:

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

і ви отримуєте:

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

як це працює : ви використовуєте Node.js для завантаження модуля JS, який створює об'єкт JS, який легко може бути розширений JSON Node.js. Параметр -e оцінює рядок, і -pпараметр повторює результат повернення останньої операції Node.js до stdout.

Якщо ви хочете завантажити .js-скрипт, який знаходиться в іншому робочому каталозі, вам слід переключити рядки "" і "":

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

-4

Спробуйте використовувати base64закодоване рядок. Працював для мене більшу частину часу.

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

після base64кодованого рядка виглядають як

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

base64 кодування та декодування доступні на всіх мовах.


7
Для його відображення потрібен спеціальний код, ви перетворюєте рядок у масив. Це не рішення
tom10271

3
Я думаю, що це погана ідея - вона необгрунтовує зміст вмісту і вимагає додаткового коду, часу, пам'яті та інструментів для його створення та споживання. Сканування через рядок і заміна спеціальних символів, звичайно, вимагає додаткового коду, часу та пам'яті, але, безумовно, менше, ніж кодування та декодування base64
Semanino

Це погана ідея, оскільки читабельність JSON зникла, а також, як згадується @ tom10271, вам потрібна додаткова операція, щоб використовувати json
T90

-23

помістіть текст рядка у файл txt, а потім

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

(працює над mongoDB)


11
-1: це хибна відповідь. Він не є дійсним JSON і не працює в JavaScript, оскільки функція не названа cat.
Мартін Шухфус
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.