Многострочные строки в формате JSON


657

Я пишу некоторые файлы данных в формате JSON и хотел бы, чтобы некоторые действительно длинные строковые значения были разбиты на несколько строк. Используя JSON-модуль Python, я получаю массу ошибок, использую ли я \или \nкак выход.

Возможно ли иметь многострочные строки в JSON? Это в основном для визуального комфорта, поэтому я полагаю, что я могу просто включить перенос слов в моем редакторе, но мне просто любопытно ...



1
структурируйте свои данные: разбейте многострочную строку на массив строк, а затем объедините их позже.
RubyTuesdayDONO

2
Попробуйте инструмент HJSON. Он преобразует вашу многострочную строку в формате json в правильный формат json.
Гаурав

Возможный дубликат значения Can JSON может содержать многострочную строку
Flimzy

Ответы:


403

JSON не допускает реальных разрывов строк. Вам нужно заменить все разрывы строк на \n.

например:

"first line second line"

можно сохранить с помощью:

"first line\nsecond line"

Замечания:

ибо Pythonэто должно быть записано как:

"first line\\nsecond line"

где \\для экранирования обратной косой черты, в противном случае python будет рассматриваться \nкак управляющий символ "новая строка"


89
-1 ОП в использовании «\ N» последовательности. Это не работает, потому что они не экранируют обратную косую черту , как "\\ n", поэтому Python преобразует escape-последовательность в символ новой строки, а не оставляет ее буквально с обратной косой чертой, за которой следует en, как того требует JSON.
user359996

6
@ user359996 Я не уверен, что это правда. Для меня (хранение данных в JSON с помощью just \nи вывод их через Curses), \nпохоже, работает нормально. Кажется, это зависит от движка представления / рендеринга.
ashes999

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

5
@Nawaz: "\ n" и "\ r" являются escape-последовательностями для перевода строки и возврата каретки, соответственно. Они не являются буквальными символами перевода строки и возврата каретки . В качестве дополнительного примера, чтобы сделать его более понятным, учтите, что «\\» является escape-последовательностью для обратной косой черты, в отличие от буквальной обратной косой черты. Грамматика JSON явно исключает управляющие символы (см. Определение «char») и вместо этого обеспечивает их представление через escape-последовательности (\\, \ r, \ n и т. Д.).
user359996

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
Это показывает, как вставить новую строку в строках, что не отвечает на вопрос. Этот ответ делает.
Фгриу

1
fgrieu - можно так же легко объединить строки без добавления новой строки. С этим небольшим изменением он обеспечивает обходной путь для многострочных строк (пока вы контролируете указание схемы JSON). Я постараюсь улучшить ответ с этим.
дроб

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 может принимать следующие значения:

  • any-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" в качестве escape.

Но имейте в виду: если вы используете строку в 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
cat

9

Используйте регулярные выражения, чтобы заменить все вхождения \r\nс \\n.

Это сработало для меня в Scala.

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 в стандартный вывод.

Если вы хотите загрузить скрипт .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

поместите многострочный текст в текстовый файл, а затем

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.