web-dev-qa-db-fra.com

Une valeur JSON peut-elle contenir une chaîne multiligne

J'écris un fichier JSON qui serait lu par un programme Java. Le fragment est comme suit ...

{
  "testCases" :
  {
    "case.1" :
    {
      "scenario" : "this the case 1.",
      "result" : "this is a very long line which is not easily readble.
                  so i would like to write it in multiple lines.
                  but, i do NOT require any new lines in the output.
                  I need to split the string value in this input file only.
                  such that I don't require to slide the horizontal scroll again and again while verifying the correctness of the statements.
                  the prev line, I have shown, without splitting just to give a feel of my problem"
    }
  }
}
87
user2409155

Découvrez les spécifications ! La production char de la grammaire JSON peut prendre les valeurs suivantes:

  • (n'importe quel caractère Unicode, sauf -"- ou -\- ou caractère de contrôle)
  • \"
  • \\
  • \/
  • \b
  • \f
  • \n
  • \r
  • \t
  • \u _ {quatre-hex-digits} _

Les nouvelles lignes sont des "caractères de contrôle", alors non, vous ne pouvez pas avoir de nouvelle ligne littérale dans votre chaîne. Cependant, vous pouvez l'encoder en utilisant la combinaison de \n et \r dont vous avez besoin.

L'outil JSONLint confirme que votre JSON n'est pas valide.


Update: Et si vous voulez écrire des retours à la ligne dans votre syntaxe JSON sans inclure réellement les retours à la ligne dans les données, vous avez encore plus de chance. Bien que JSON soit destiné à être humain dans une certaine mesure, il l'est toujours data et vous essayez d'appliquer un formatage arbitraire à ces données. Ce n'est absolument pas ce que JSON est sur.

Je ne suis pas sûr de votre exigence exacte, mais une solution possible pour améliorer la "lisibilité" consiste à la stocker sous forme de tableau.

{
  "testCases" :
  {
    "case.1" :
    {
      "scenario" : "this the case 1.",
      "result" : ["this is a very long line which is not easily readble.",
                  "so i would like to write it in multiple lines.",
                  "but, i do NOT require any new lines in the output."]
    }
  }
}

}

La rejoindre dans le dos à chaque fois que nécessaire avec 

result.join(" ")
25
Brian McAuliffe

Si j'ai bien compris, la question ne concerne pas comment passer une chaîne avec des symboles de contrôle en utilisant json, mais comment stocker et restaurer json dans un fichier où vous pouvez scinder une chaîne avec des symboles de contrôle d'éditeur.

Si vous souhaitez stocker une chaîne multiligne dans un fichier, votre fichier ne stockera pas l'objet json valide. Mais si vous utilisez uniquement vos fichiers json dans votre programme, vous pouvez alors stocker les données comme vous le souhaitez et supprimer manuellement les nouvelles lignes du fichier à chaque fois que vous les chargez dans votre programme, puis passez à l'analyseur Json.

Ou bien, ce qui serait mieux, vous pouvez avoir vos fichiers de source de données json dans lesquels vous modifiez une copie à votre guise, puis supprimer toutes les nouvelles lignes avec un utilitaire dans le fichier json valide utilisé par votre programme.

3

Pas très bonne solution, mais vous pouvez essayer l'outil hjson. Lien . Il vous permet d'écrire du texte sur plusieurs lignes dans l'éditeur, puis de le convertir au format JSON correct approprié. Remarque: ajoute les caractères "\ n" aux nouvelles lignes, mais vous pouvez simplement les supprimer dans n’importe quel éditeur de texte avec la fonction "Remplacer tout ..". 

P.S. Devrait être un commentaire sur la question, mais ne pas avoir assez de pension, désolé.

2
CodeMonkey

Je crois que cela dépend de l'interpréteur JSON que vous utilisez ... en javascript, vous pouvez utiliser des terminateurs de ligne

{
  "testCases" :
  {
    "case.1" :
    {
      "scenario" : "this the case 1.",
      "result" : "this is a very long line which is not easily readble. \
                  so i would like to write it in multiple lines. \
                  but, i do NOT require any new lines in the output."
    }
  }
}
1
Elric Best

Ceci est implémenté en tant qu'écrivain car pour le caractère unique, il peut y avoir plusieurs caractères de sortie. Je ne pouvais pas imaginer cela en tant que lecteur. Assez lourd pour la tâche mais assez extensible.

String multilineJson = "{\n" +
        "prop1 = \"value1\",\n" +
        "prop2 = \"multi line\n" +
        "value2\"\n" +
        "}\n";
String multilineJsonExpected = "{\n" +
        "prop1 = \"value1\",\n" +
        "prop2 = \"multi line\\nvalue2\"\n" +
        "}\n";

StringWriter sw = new StringWriter();
JsonProcessor jsonProcessor = new JsonProcessor(sw);
jsonProcessor.write(multilineJson);

assertEquals(multilineJsonExpected, sw.toString());

La mise en oeuvre

public class JsonProcessor extends FilterWriter {

    private char[] curr;
    private int currIdx;

    private boolean doubleQuoted;

    public JsonProcessor(Writer out) {
        super(out);
    }

    @Override
    public void write(String str) throws IOException {
        char[] arr = str.toCharArray();
        write(arr, 0, arr.length);
    }

    @Override
    synchronized public void write(char[] cbuf, int off, int len) throws IOException {
        curr = Arrays.copyOfRange(cbuf, off, len - off);
        for (currIdx = 0; currIdx < curr.length; currIdx++) {
            processChar();
        }
    }

    private void processChar() throws IOException {
        switch (currentChar()) {
            case '"':
                processDoubleQuotesSymbol();
                break;
            case '\n':
            case '\r':
                processLineBreakSymbol();
                break;
            default:
                write(currentChar());
                break;
        }
    }

    private void processDoubleQuotesSymbol() throws IOException {
        doubleQuoted = !doubleQuoted;
        write('"');
    }

    private void processLineBreakSymbol() throws IOException {
        if (doubleQuoted) {
            write('\\');
            write('n');
            if (lookAhead() == '\n' || lookAhead() == '\r') {
                currIdx++;
            }
        } else {
            write(currentChar());
        }
    }

    private char currentChar() {
        return curr[currIdx];
    }

    private char lookAhead() {
        if (currIdx >= curr.length) {
            return 0;
        }
        return curr[currIdx + 1];
    }
}
0
Mykhaylo Adamovych