Konvertieren Sie JSON-Zeichenfolgen mit Jackson in Pretty Print JSON-Ausgaben

165

Dies ist die JSON-Zeichenfolge, die ich habe:

{"attributes":[{"nm":"ACCOUNT","lv":[{"v":{"Id":null,"State":null},"vt":"java.util.Map","cn":1}],"vt":"java.util.Map","status":"SUCCESS","lmd":13585},{"nm":"PROFILE","lv":[{"v":{"Party":null,"Ads":null},"vt":"java.util.Map","cn":2}],"vt":"java.util.Map","status":"SUCCESS","lmd":41962}]}

Ich muss den obigen JSON Stringin Pretty Print JSON Output (mit Jackson) konvertieren , wie unten:

{
    "attributes": [
        {
            "nm": "ACCOUNT",
            "lv": [
                {
                    "v": {
                        "Id": null,
                        "State": null
                    },
                    "vt": "java.util.Map",
                    "cn": 1
                }
            ],
            "vt": "java.util.Map",
            "status": "SUCCESS",
            "lmd": 13585
        },
        {
            "nm": "PROFILE
            "lv": [
                {
                    "v": {
                        "Party": null,
                        "Ads": null
                    },
                    "vt": "java.util.Map",
                    "cn": 2
                }
            ],
            "vt": "java.util.Map",
            "status": "SUCCESS",
            "lmd": 41962
        }
    ]
}

Kann mir jemand ein Beispiel geben, das auf meinem obigen Beispiel basiert? Wie kann dieses Szenario erreicht werden? Ich weiß, dass es viele Beispiele gibt, aber ich kann diese nicht richtig verstehen. Jede Hilfe wird anhand eines einfachen Beispiels geschätzt.

Aktualisiert:

Unten ist der Code, den ich benutze:

ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.defaultPrettyPrintingWriter().writeValueAsString(jsonString));

Dies funktioniert jedoch nicht so, wie ich die Ausgabe wie oben erwähnt benötigt habe.

Hier ist das POJO, das ich für den obigen JSON verwende:

public class UrlInfo implements Serializable {

    private List<Attributes> attribute;

}

class Attributes {

    private String nm;
    private List<ValueList> lv;
    private String vt;
    private String status;
    private String lmd;

}


class ValueList {
    private String vt;
    private String cn;
    private List<String> v;
}

Kann mir jemand sagen, ob ich das richtige POJO für den JSON habe oder nicht?

Aktualisiert:

String result = restTemplate.getForObject(url.toString(), String.class);

ObjectMapper mapper = new ObjectMapper();
Object json = mapper.readValue(result, Object.class);

String indented = mapper.defaultPrettyPrintingWriter().writeValueAsString(json);

System.out.println(indented);//This print statement show correct way I need

model.addAttribute("response", (indented));

Die folgende Zeile druckt ungefähr so ​​aus:

System.out.println(indented);


{
  "attributes" : [ {
    "nm" : "ACCOUNT",
    "error" : "null SYS00019CancellationException in CoreImpl fetchAttributes\n java.util.concurrent.CancellationException\n\tat java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:231)\n\tat java.util.concurrent.FutureTask.",
    "status" : "ERROR"
  } ]
}

So musste ich gezeigt werden. Aber wenn ich es zu einem Modell wie diesem hinzufüge:

model.addAttribute("response", (indented));

Und zeigt es dann auf einer Ergebnisformular-JSP-Seite wie unten:

    <fieldset>
        <legend>Response:</legend>
            <strong>${response}</strong><br />

    </fieldset>

Ich bekomme so etwas:

{ "attributes" : [ { "nm" : "ACCOUNT", "error" : "null    
SYS00019CancellationException in CoreImpl fetchAttributes\n 
java.util.concurrent.CancellationException\n\tat 
java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:231)\n\tat 
java.util.concurrent.FutureTask.", "status" : "ERROR" } ] }

was ich nicht brauche. Ich brauchte die Art und Weise, wie es oben ausgedruckt wurde. Kann mir jemand sagen, warum es so passiert ist?

Arsenal
quelle

Antworten:

251

Um einen alten JSON einzurücken, binden Sie ihn einfach wie Objectfolgt:

Object json = mapper.readValue(input, Object.class);

und dann schreibe es mit Einrückung aus:

String indented = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(json);

Dadurch müssen Sie kein tatsächliches POJO definieren, dem Daten zugeordnet werden sollen.

Oder Sie können auch JsonNode(JSON Tree) verwenden.

StaxMan
quelle
Danke StaxMan, ich denke das funktioniert. Wenn ich eingerückt drucke, komme ich in die Richtung, die ich brauchte. Aber wenn ich Einrückungen verwende, um sie dem Modell hinzuzufügen, damit ich sie auf der Ergebnisformularseite anzeigen kann. Es wird immer noch in zwei drei Zeilen gedruckt. Ich habe die Frage aktualisiert. Vielleicht bekommen Sie eine Vorstellung davon, was jetzt passiert.
Arsenal
Das Problem ist dann mit Spring - ich denke, es erwartet ein POJO als Attribut und keinen vorformatierten String. Anstatt zu versuchen, es selbst zu formatieren, müssen Sie Spring anweisen, dies zu tun. Wenn Sie Jackson verwenden, sollte es möglich sein, es für die Verwendung von Einrückungen zu konfigurieren. Obwohl ich ehrlich bin, bin ich mir nicht sicher, warum Sie es überhaupt einrücken müssen, um eine Antwort zu erhalten.
StaxMan
30
Hallo, defaultPrettyPrintingWriter () ist veraltet. Verwenden Sie seit 1.9 stattdessen writerWithDefaultPrettyPrinter (). Siehe: jackson.codehaus.org/1.9.0/javadoc/org/codehaus/jackson/map/…
Browny Lin
6
Verwenden Sie für Jackson 2 SerializationFeature.INDENT_OUTPUT, wie von Marcelo C. unten angegeben
Mike R
Haben Sie eine Idee, wie Sie den Betrag des schriftlichen Werts mit Jackson veröffentlichen können?
Reyansh Mishra
124

Die einfachste und zugleich kompakteste Lösung (für v2.3.3):

ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
mapper.writeValueAsString(obj)
Marcelo C.
quelle
21
Sie können das sogar noch weiter verkürzen: ObjectMapper mapper = new ObjectMapper.enable (SerializationFeature.INDENT_OUTPUT);
Jason Nichols
26

Der neue Weg mit Jackson 1.9+ ist der folgende:

Object json = OBJECT_MAPPER.readValue(diffResponseJson, Object.class);
String indented = OBJECT_MAPPER.writerWithDefaultPrettyPrinter()
                               .writeValueAsString(json);

Die Ausgabe wird korrekt formatiert!

Marcello de Sales
quelle
1
Leider hilft das nicht, wenn meine Eingabe ein zur Laufzeit erstelltes Objekt ist, kein anderes JSON.
Innokenty
@Innokenty Dann überspringe die erste Zeile.
Hammelfleisch
2
@muttonUp Ja, offensichtlich. Ich habe es sogar getan, ich weiß nicht, warum ich so einen dummen Kommentar hinterlassen habe =)
Innokenty
17

Für Jackson 1.9 können wir den folgenden Code für hübschen Druck verwenden.

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.enable(SerializationConfig.Feature.INDENT_OUTPUT);
Scalauser
quelle
11

Ich denke, dies ist die einfachste Technik, um die JSON-Daten zu verschönern.

String indented = (new JSONObject(Response)).toString(4);

Dabei ist Response ein String.

Geben Sie einfach die 4 (indentSpaces) ein toString() Methode.

Hinweis: Es funktioniert gut in Android ohne Bibliothek. In Java müssen Sie jedoch die Bibliothek org.json verwenden.

Aman Gupta - SHOoTeR
quelle
3
Erwähnenswert ist die Verwendung der Bibliothek JSON in Java (org.json) .
Steve Chambers
In Android kann es direkt ohne Bibliothek verwenden.
Aman Gupta - ShoTeR
String json = new GsonBuilder().setPrettyPrinting().create().toJson(map); String indentedJson = (new JSONObject(json)).toString(4);Aus irgendeinem Grund verliert der zweite die Reihenfolge der Schlüssel
Michail Michailidis
Der aktuelle Ansatz verarbeitet leider keine Liste von JSON-Objekten. Ich meine [{"id": "1"}, {"id": "2"}]
Geniy
4

Dies scheint die Antwort auf Ihre Frage zu sein . Es heißt, es wird Spring verwendet, aber ich denke, das sollte Ihnen in Ihrem Fall trotzdem helfen. Lassen Sie mich den Code hier einfügen, damit er bequemer ist:

import java.io.FileReader;

import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.ObjectWriter;

public class Foo
{
  public static void main(String[] args) throws Exception
  {
    ObjectMapper mapper = new ObjectMapper();
    MyClass myObject = mapper.readValue(new FileReader("input.json"), MyClass.class);
    // this is Jackson 1.x API only: 
    ObjectWriter writer = mapper.defaultPrettyPrintingWriter();
    // ***IMPORTANT!!!*** for Jackson 2.x use the line below instead of the one above: 
    // ObjectWriter writer = mapper.writer().withDefaultPrettyPrinter();
    System.out.println(writer.writeValueAsString(myObject));
  }
}

class MyClass
{
  String one;
  String[] two;
  MyOtherClass three;

  public String getOne() {return one;}
  void setOne(String one) {this.one = one;}
  public String[] getTwo() {return two;}
  void setTwo(String[] two) {this.two = two;}
  public MyOtherClass getThree() {return three;}
  void setThree(MyOtherClass three) {this.three = three;}
}

class MyOtherClass
{
  String four;
  String[] five;

  public String getFour() {return four;}
  void setFour(String four) {this.four = four;}
  public String[] getFive() {return five;}
  void setFive(String[] five) {this.five = five;}
}
Daniel Kaplan
quelle
Danke Daniel für die Hilfe. Das Schwierigste, was ich habe, ist, wie ich meinen JSON in eine Klasse modellieren kann. Wenn ich diesen Teil zum Laufen bringe, kann ich den Rest leicht codieren.
Arsenal
Können Sie einen Blick in meine POJO-Klasse werfen, die ich aus dem JSON geschrieben habe? Es sieht richtig aus oder nicht?
Arsenal
3

Sie können dies auf folgende Weise erreichen:

1. Verwenden von Jackson von Apache

    String formattedData=new ObjectMapper().writerWithDefaultPrettyPrinter()
.writeValueAsString(YOUR_JSON_OBJECT);

Folgende Klasse importieren:

import com.fasterxml.jackson.databind.ObjectMapper;

Die Gradle-Abhängigkeit ist:

compile 'com.fasterxml.jackson.core:jackson-core:2.7.3'
compile 'com.fasterxml.jackson.core:jackson-annotations:2.7.3'
compile 'com.fasterxml.jackson.core:jackson-databind:2.7.3'

2. Verwenden von Gson von Google

String formattedData=new GsonBuilder().setPrettyPrinting()
    .create().toJson(YOUR_OBJECT);

Folgende Klasse importieren:

import com.google.gson.Gson;

Es ist gradle ist:

compile 'com.google.code.gson:gson:2.8.2'

Hier können Sie die richtige aktualisierte Version aus dem Repository herunterladen.

Md. Sajedul Karim
quelle
2

ObjectMapper.readTree() kann dies in einer Zeile tun:

mapper.writerWithDefaultPrettyPrinter().writeValueAsString(mapper.readTree(json));
Praneeth
quelle
1
Der Grund, warum mir diese Antwort gefällt, ist, dass sie überhaupt keine Objektkonvertierung außer der direkten Zuordnung zu JSON-Typen durchführt. Solange die Eingabezeichenfolge gültiges JSON ist, wissen wir, dass die Ausgabezeichenfolge semantisch äquivalent zu JSON ist.
M. Justin