Chaînes multilignes en JSON

656

J'écris des fichiers de données au format JSON et j'aimerais avoir de très longues valeurs de chaîne réparties sur plusieurs lignes. En utilisant le module JSON de python, j'obtiens beaucoup d'erreurs, que j'utilise \ou \nque j'échappe.

Est-il possible d'avoir des chaînes multi-lignes en JSON? C'est principalement pour le confort visuel, donc je suppose que je peux simplement activer le retour à la ligne dans mon éditeur, mais je suis juste un peu curieux ...

Anonnobody
la source
1
structurez vos données: divisez la chaîne multiligne en un tableau de chaînes, puis joignez-les plus tard.
RubyTuesdayDONO
2
Essayez l'outil hjson. Il convertira votre chaîne multiligne en json au format json approprié.
gaurav
Un double possible de Can a JSON value
contain a

Réponses:

403

JSON n'autorise pas les sauts de ligne réels. Vous devez remplacer tous les sauts de ligne par \n.

par exemple:

"first line second line"

peut enregistré avec:

"first line\nsecond line"

Remarque:

car Python, cela devrait être écrit comme suit:

"first line\\nsecond line"

\\est pour échapper la barre oblique inverse, sinon python traitera \ncomme le caractère de contrôle "nouvelle ligne"

VOUS
la source
89
-1 L'OP est d' utiliser le « \ n » séquence d'échappement. Cela ne fonctionne pas car ils n'échappent pas à la barre oblique inverse , comme "\\ n", donc Python convertit la séquence d'échappement en caractère de nouvelle ligne plutôt que de la laisser comme littéralement une barre oblique inverse suivie d'un en, comme l'exige JSON.
user359996
6
@ user359996 Je ne suis pas sûr que ce soit vrai. Pour moi (stocker des données dans JSON avec juste \net les diffuser via Curses), cela \nsemble fonctionner correctement. Cela dépend du moteur de visualisation / rendu, semble-t-il.
ashes999
2
Les séquences de nouvelle ligne sont en effet spécifiques à la plate-forme (cf. en.wikipedia.org/wiki/Newline#Representations ). Cependant, selon @Lightness Races dans la réponse d'Orbit, ni les caractères de retour de curseur ni de saut de ligne ne figurent dans la grammaire JSON. En fait, je ne suis pas un programmeur Python, donc je ne suis pas sûr de ce qui se passe dans votre cas, mais soit votre analyseur est cassé, soit vous ne passez pas ce que vous pensez être. Peut-être que cette réponse l'explique mieux: stackoverflow.com/a/9295597/359996 . Notez en particulier le peu de double échappement.
user359996
5
@Nawaz: "\ n" et "\ r" sont des séquences d'échappement pour le saut de ligne et le retour chariot, respectivement. Ils ne sont pas les contrôle littéral et saut de ligne retour chariot personnages . Comme exemple supplémentaire pour le rendre plus clair, considérez que "\\" est une séquence d'échappement pour la barre oblique inverse, par opposition à une barre oblique inverse littérale. La grammaire JSON exclut explicitement les caractères de contrôle (cf. la définition "char"), et prévoit à la place leur représentation via des séquences d'échappement (\\, \ r, \ n, etc.).
user359996
2
@ user359996: Oui .. Je l'ai vu plus tard, bien que je garde mon ancien commentaire en tant que tel, au cas où quelqu'un d'autre aurait le même doute, notre discussion pourrait l'aider. merci de l'avoir confirmé BTW.
Nawaz
197

J'ai dû le faire pour un petit projet Node.js et j'ai trouvé cette solution :

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

 ],
}

Cela me semble assez soigné, à part que je dois utiliser des guillemets partout. Bien que sinon, je pourrais peut-être utiliser YAML, mais cela a d'autres pièges et n'est pas pris en charge nativement. Une fois analysé, j'utilise simplement myData.modify_head.join('\n')ou myData.modify_head.join(), selon que je veux ou non un saut de ligne après chaque chaîne.

errordeveloper
la source
40
Il s'agit d'une solution pour un cadre spécifique, pas nécessairement lié à la question. Ce que vous créez n'est pas des chaînes multilignes (ce qui n'est pas possible de toute façon), mais des tableaux avec des chaînes à l'intérieur
Samuel Rivas
3
Cela montre comment insérer une nouvelle ligne dans des chaînes, ce qui ne répond PAS à la question. Cette réponse fait.
fgrieu
1
fgrieu - on pourrait tout aussi bien concaténer les chaînes sans ajouter de nouvelle ligne. Avec cette petite modification, il fournit une solution de contournement pour les chaînes multilignes (tant que vous contrôlez la spécification du schéma JSON). Je vais essayer d'améliorer la réponse avec cela.
drrob
1
Merci, j'aime ça. Je vais avec cela pour ce que je travaille. Il a l'air soigné et organisé. Je vais avoir chaque nouvelle ligne dans ce tableau impliquer un saut de ligne dans le texte sorti, bien que cette solution puisse également fonctionner pour les cas où vous n'insérez pas de sauts de ligne. J'ai déjà utilisé cette solution dans mon code source javascript simplement parce que j'aimais son organisation et qu'elle ne laisse aucun doute quant aux types d'espaces à insérer dans la chaîne finale.
Gal
Malgré les réserves de l'inventeur JSON, je viens de l'utiliser pour ajouter des commentaires (sans la partie javascript, mais seulement les [] et les virgules) pour ajouter des commentaires afin d'aider un éventuel futur responsable qui pourrait modifier manuellement mon petit fichier JSON.
Whirl Mind
117

Malheureusement, la plupart des réponses ici abordent la question de savoir comment mettre un caractère de nouvelle ligne dans les données de chaîne. La question est de savoir comment rendre le code plus agréable en divisant la valeur de chaîne sur plusieurs lignes de code. (Et même les réponses qui reconnaissent cela fournissent des "solutions" qui supposent que l'on est libre de changer la représentation des données, ce qui dans de nombreux cas ne l'est pas.)

Et la pire nouvelle est qu'il n'y a pas de bonne réponse.

Dans de nombreux langages de programmation, même s'ils ne prennent pas explicitement en charge le fractionnement de chaînes sur plusieurs lignes, vous pouvez toujours utiliser la concaténation de chaînes pour obtenir l'effet souhaité; et tant que le compilateur n'est pas terrible, c'est bien.

Mais json n'est pas un langage de programmation; c'est juste une représentation des données. Vous ne pouvez pas lui dire de concaténer des chaînes. Sa grammaire (assez petite) n'inclut pas non plus la possibilité de représenter une chaîne sur plusieurs lignes.

À moins de concevoir un pré-processeur d'une sorte (et pour ma part, je n'ai pas envie de créer efficacement mon propre langage pour résoudre ce problème), il n'y a pas de solution générale à ce problème. SI vous pouvez changer le format des données, vous pouvez alors remplacer un tableau de chaînes. Sinon, c'est l'une des nombreuses façons dont json n'est pas conçu pour être lisible par l'homme.

Mark Adelsberger
la source
3
On ne sait pas trop ce que l'OP veut, des sauts de ligne dans la chaîne, ou mieux organiser la chaîne ...
9ilsdx 9rvj 0lo
3
@ 9ilsdx9rvj0lo: Non, ce n'est pas le cas.
Mark Adelsberger
Concernant "La question est de savoir comment rendre le code plus agréable en divisant la valeur de chaîne sur plusieurs lignes de code ...": pour une solution aux instructions multilignes en Python, voir stackoverflow.com/questions/53162/… . Il existe une différence entre JSON multiligne et Python multiligne. JSON multiligne utilise '\' suivi de 'n' dans le JSON, c'est-à-dire "\ n" dans la chaîne. Instructions Python sur plusieurs lignes, utilisez «\» suivi de «\ n», c'est-à-dire une barre oblique inversée de fin sur la ligne à poursuivre. Format Windows: remplacez \ n par \ r \ n le cas échéant!
Ivan
106

Consultez les spécifications ! La grammaire de JSON omble de production peut prendre les valeurs suivantes:

  • tout-caractère-Unicode-sauf- "ou \-ou-caractère-de-contrôle
  • \"
  • \\
  • \/
  • \b
  • \f
  • \n
  • \r
  • \t
  • \u quatre chiffres hexadécimaux

Les sauts de ligne sont des "caractères de contrôle", donc, non, vous ne pouvez pas avoir de saut de ligne littéral dans votre chaîne. Cependant, vous pouvez l'encoder en utilisant n'importe quelle combinaison de \net que \rvous souhaitez.

Courses de légèreté en orbite
la source
3
C'est la bonne réponse car elle ne laisse aucune ambiguïté. Les nouvelles lignes sont autorisées, selon la spécification, tant qu'elles sont correctement échappées avec le caractère de contrôle.
Ryan
@AliKhaki \ n en JSON n'atteindra pas le résultat recherché par la question. Soit vous pensez à autre chose (c'est-à-dire incorporer des caractères de nouvelle ligne), soit vous parlez d'une nouvelle ligne dans un littéral de chaîne (contenant JSON) dans un langage de programmation, ce qui est encore quelque chose de différent.
Courses de légèreté en orbite
@LightnessRacesinOrbit oui je recherche une nouvelle ligne dans la chaîne
Ali Khaki
46

JSON n'autorise pas les lignes de rupture pour plus de lisibilité.

Votre meilleur pari est d'utiliser un IDE qui fera un retour à la ligne pour vous.

James Gentes
la source
1
Un éditeur comme BBEdit qui prend en charge le retour à la ligne "doux" est idéal. Il encapsule le texte pour qu'il apparaisse dans la zone visible de la fenêtre de l'éditeur, mais seules les fins de ligne que vous saisissez (par exemple, le retour chariot) sont conservées dans le fichier lors de son enregistrement. Facilite l'édition de JSON avec de très longues chaînes sans avoir à recourir à des astuces de code ou à des hacks.
cshotton
44

C'est une très vieille question, mais je suis tombé sur cette recherche et je pense que je connais la source de votre problème.

JSON n'autorise pas les "vraies" nouvelles lignes dans ses données; il ne peut avoir échappé qu'aux nouvelles lignes. Voir la réponse de @YOU . Selon la question, il semble que vous ayez tenté d'échapper aux sauts de ligne en Python de deux manières: en utilisant le caractère de continuation de ligne ( "\") ou en l'utilisant "\n"comme d'échappement.

Mais gardez à l'esprit: si vous utilisez une chaîne en python, les caractères d'échappement spéciaux ( "\t", "\n") sont traduits en caractères de contrôle réels! Le "\n"sera remplacé par le caractère de contrôle ASCII représentant un caractère de nouvelle ligne, qui est précisément le caractère non autorisé dans JSON. (Quant au caractère de continuation de ligne, il supprime simplement la nouvelle ligne.)

Donc, ce que vous devez faire est d'empêcher Python d'échapper aux caractères. Vous pouvez le faire en utilisant une chaîne brute (placée rdevant la chaîne, comme dans r"abc\ndef", ou en incluant une barre oblique supplémentaire devant la nouvelle ligne ( "abc\\ndef").

Au lieu de remplacer "\n"par le vrai caractère de contrôle ASCII de nouvelle ligne, les deux éléments ci-dessus resteront "\n"sous la forme de deux caractères littéraux, que JSON pourra alors interpréter comme un échappement de nouvelle ligne.

HardlyKnowEm
la source
12

Ecrivez la valeur de la propriété sous forme de tableau de chaînes. Comme exemple donné ici https://gun.io/blog/multi-line-strings-in-json/ . CA aidera.

Nous pouvons toujours utiliser un tableau de chaînes pour les chaînes multilignes comme suit.

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

Et nous pouvons facilement parcourir le tableau pour afficher le contenu sur plusieurs lignes.

Sandip Nirmal
la source
1
Je vous suggère d'ajouter les informations dans votre réponse à partir du lien, car les liens peuvent se rompre à l'avenir.
YoungHobbit
5
Mais eux, vous avez un tableau, pas une chaîne. Un tableau n'est pas une chaîne. Période.
9ilsdx 9rvj 0lo
Pensais juste à ça. Agréable!
Phillip Jacobs
12

Utilisez json5 (chargeur) voir https://json5.org/ - exemple (par json5)

{
  lineBreaks: "Look, Mom! \
No \\n's!",
}
Lacom
la source
La question posée par le PO. Au moins s'il peut utiliser json5.
nomen
10

Est-il possible d'avoir des chaînes multi-lignes en JSON?

Oui. Je viens de le tester maintenant avec mon navigateur Web Firefox en appuyant sur F12, en cliquant sur la console et en tapant en bas de l'écran.

x={text:"hello\nworld"}

L'objet x vient d'être créé à partir d'une chaîne au format JSON contenant une chaîne multiligne.

console.log(x.text)
hello
world

x.text s'affiche, montrant qu'il s'agit d'une chaîne de plusieurs lignes.

Ces deux tests montrent que l'interpréteur Javascript de Firefox est heureux de créer et d'utiliser JSON avec des chaînes multilignes.

Plus de tests avec JSON.stringifyet JSON.parseont montré que l'interpréteur Javascript peut convertir un objet contenant des chaînes multilignes en JSON et le réanalyser sans aucun problème.

Dans le passé, j'ai stocké l'intégralité des œuvres de Shakespeare en tant que propriété dans un objet JSON, puis je l'ai envoyé sur Internet, sans altération.

Exemple

Voici une chaîne de deux lignes entrée sur trois lignes

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

On peut afficher l'objet

console.log(x)

donnant

Object { text: "experts\nexchange" }

ou la chaîne

console.log(x.text)

donnant

experts
exchange

La fin des lignes de la chaîne résulte de l'utilisation de \ n et les multiples lignes d'entrée sont obtenues en utilisant juste \ à la fin de la ligne.

En pratique, vous voudrez peut-être synchroniser vos fins de ligne avec celles de la chaîne, par exemple

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

Longueur de chaîne multiligne

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

Notez que la chaîne avec la nouvelle ligne n'est pas plus longue que la chaîne avec l'espace. Même si deux caractères ont été tapés sur le clavier ('\' et 'n'), un seul caractère est stocké dans la chaîne.

Ivan
la source
3
Un lecteur de format de chaîne JavaScript n'est pas un lecteur de format de chaîne JSON et vice versa, donc pendant que cela fonctionne, la console JavaScript accepte également x={"a":NaN}et x={"a":"a \<literal newline with SHIFT>b"}, qui ne sont pas JSON, mais sont JavaScript
cat
9

Utilisez regex pour remplacer toutes les occurrences de \r\navec \\n.

Cela a fonctionné pour moi dans scala.

val newstr = str.replace("\r\n", "\\n")
Sikander
la source
Pourquoi les 3 contre-obliques?
neXus
6
@neXus Je ne sais pas pourquoi mais quelqu'un l'a édité en 3 barres obliques inverses. Merci à LightnessRacesInOrbit pour le corriger.
Sikander
5

Si vous souhaitez utiliser Node.js, vous pouvez le faire:

module.exports = {

  multilineStr: `

     dis my life 
     it's now or never

  `

}

vous pouvez importer avec Node.js et le convertir facilement en JSON comme ceci:

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

et vous obtenez:

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

comment cela fonctionne : vous utilisez Node.js pour charger un module JS, ce qui crée un objet JS qui peut facilement être stratifié JSON par Node.js. L'option -e évalue la chaîne et l' -poption renvoie le résultat de retour de la dernière opération Node.js à stdout.

Si vous voulez charger un script .js qui se trouve dans un répertoire de travail différent, vous devez changer les chaînes "" et '':

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

Essayez d'utiliser base64une valeur de chaîne codée. Travaillé pour moi la plupart du temps.

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

après que la base64chaîne codée ressemble

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

L'encodage et le décodage base64 sont disponibles dans toutes les langues.

Sunit Parekh
la source
7
Vous avez besoin d'un code spécial pour l'afficher, vous transformez une chaîne en tableau. Ce n'est pas une solution
tom10271
3
Je pense que c'est une mauvaise idée - cela obstrue le contenu inutilement et nécessite du code, du temps, de la mémoire et des outils supplémentaires pour le produire et le consommer. Bien sûr, parcourir la chaîne et remplacer les caractères spéciaux nécessite du code, du temps et de la mémoire supplémentaires, mais certainement moins que l'encodage et le décodage base64
Semanino
C'est une mauvaise idée car la lisibilité du JSON a disparu, et aussi comme @ tom10271 mentionné, vous avez besoin d'une opération supplémentaire pour utiliser le json
T90
-23

mettre le texte multiligne sur le fichier txt puis

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

(ça marche sur mongoDB)

flaalf
la source
11
-1: c'est une réponse trompeuse. Ce n'est ni un JSON valide ni ne fonctionne en javascript car il n'y a pas de fonction nommée cat.
Martin Schuhfuß