Konwertuj ciąg JSON na wyjście JSON Pretty Print przy użyciu Jacksona

165

To jest ciąg JSON, który mam:

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

Muszę przekonwertować powyższy JSON Stringna Pretty Print JSON Output (używając Jacksona), jak poniżej:

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

Czy ktoś może podać mi przykład na podstawie mojego przykładu powyżej? Jak osiągnąć ten scenariusz? Wiem, że przykładów jest wiele, ale nie jestem w stanie ich właściwie zrozumieć. Każda pomoc zostanie doceniona na prostym przykładzie.

Zaktualizowano:

Poniżej kod, którego używam:

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

Ale to nie działa w sposób, w jaki potrzebowałem wyjścia, jak wspomniano powyżej.

Oto POJO, którego używam dla powyższego JSON:

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;
}

Czy ktoś może mi powiedzieć, czy mam odpowiednie POJO dla JSON, czy nie?

Zaktualizowano:

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));

Poniższa linia wyświetla coś takiego:

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"
  } ]
}

w jaki sposób powinienem być pokazany. Ale kiedy dodam to do modelu w ten sposób:

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

A następnie pokazuje to na stronie wynikowej jsp, jak poniżej:

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

    </fieldset>

Dostaję coś takiego:

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

których nie potrzebuję. Potrzebowałem sposobu, w jaki został wydrukowany powyżej. Czy ktoś może mi powiedzieć, dlaczego tak się stało?

Arsenał
źródło

Odpowiedzi:

252

Aby wciąć dowolny stary plik JSON, po prostu powiąż go jako Object, na przykład:

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

a następnie napisz z wcięciem:

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

pozwala to uniknąć konieczności definiowania rzeczywistego POJO do mapowania danych.

Możesz też użyć JsonNode(JSON Tree).

StaxMan
źródło
Dzięki StaxMan, myślę, że to działa. Kiedy drukuję z wcięciem, wchodzę w sposób, w jaki potrzebowałem. Ale kiedy używam wcięcia, aby dodać do Modelu, aby móc pokazać je na stronie formularza wyników. Nadal jest drukowany w dwóch trzech wierszach. Zaktualizowałem pytanie, może dowiesz się więcej, co się teraz dzieje.
arsenał
Problem dotyczy zatem Springa - myślę, że oczekuje on atrybutu POJO, a nie wstępnie sformatowanego ciągu znaków. Więc zamiast próbować formatować go samodzielnie, musisz powiedzieć Springowi, aby to zrobił. Podczas korzystania z Jacksona powinno być możliwe skonfigurowanie go do używania wcięć. Chociaż szczerze mówiąc, nie jestem pewien, dlaczego w ogóle trzeba go wciskać, aby uzyskać odpowiedź.
StaxMan
30
Cześć, defaultPrettyPrintingWriter () jest przestarzała. Od wersji 1.9 zamiast tego należy używać writerWithDefaultPrettyPrinter (). Zobacz: jackson.codehaus.org/1.9.0/javadoc/org/codehaus/jackson/map/…
Browny Lin,
6
W przypadku Jackson 2 użyj SerializationFeature.INDENT_OUTPUT, zgodnie z opisem Marcelo C. poniżej
Mike R
jakiś pomysł, jak opublikować kwotę wartości pisanej za pomocą jackson?
Reyansh Mishra
125

Najprostsze i jednocześnie najbardziej kompaktowe rozwiązanie (dla wersji 2.3.3):

ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
mapper.writeValueAsString(obj)
Marcelo C.
źródło
21
Właściwie możesz to jeszcze bardziej skrócić: ObjectMapper mapper = new ObjectMapper.enable (SerializationFeature.INDENT_OUTPUT);
Jason Nichols,
26

Nowy sposób korzystania z Jacksona 1.9+ jest następujący:

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

Wynik będzie poprawnie sformatowany!

Marcello de Sales
źródło
1
Niestety, to nie pomaga, jeśli moje dane wejściowe to obiekt utworzony w czasie wykonywania, a nie inny plik json.
Innokenty
@Innokenty Następnie pomiń pierwszą linię.
muttonUp
2
@muttonUp Tak, oczywiście. Nawet to zrobiłem, nie wiem czemu zostawiłem taki głupi komentarz =)
Innokenty
17

W przypadku Jacksona 1.9 możemy użyć następującego kodu, aby uzyskać ładny wydruk.

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.enable(SerializationConfig.Feature.INDENT_OUTPUT);
scalauser
źródło
11

Myślę, że to najprostsza technika upiększania danych json,

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

gdzie odpowiedź jest ciągiem.

Po prostu przekaż 4 (indentSpaces) w toString()metodzie.

Uwaga: działa dobrze na Androidzie bez żadnej biblioteki. Ale w Javie musisz użyć biblioteki org.json .

Aman Gupta - ShOoTeR
źródło
3
Warto zauważyć, że jest to użycie biblioteki JSON w Javie (org.json) .
Steve Chambers
W Androidzie może używać direclty bez żadnej biblioteki.
Aman Gupta - ShOoTeR
String json = new GsonBuilder().setPrettyPrinting().create().toJson(map); String indentedJson = (new JSONObject(json)).toString(4);z jakiegoś powodu ten drugi traci kolejność kluczy
Michail Michailidis
Obecne podejście niestety nie obsługuje listy obiektów json. Mam na myśli [{"id": "1"}, {"id": "2"}]
Geniy,
4

Wygląda na to, że może to być odpowiedź na Twoje pytanie . Mówi, że używa Springa, ale myślę, że to powinno ci pomóc w twoim przypadku. Pozwólcie, że wstawię tutaj kod, aby był wygodniejszy:

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
źródło
Dzięki Daniel za pomoc. Najtrudniejszą częścią, którą mam, jest modelowanie mojego JSON w klasę? Jeśli sprawię, że ta część będzie działać, mogę łatwo zakodować resztę.
arsenał
Czy możesz rzucić okiem na moją klasę POJO, którą napisałem z JSON? Wygląda dobrze czy nie?
arsenał
3

Możesz to osiągnąć w następujący sposób:

1. Korzystanie z Jacksona z Apache

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

Importuj poniżej klasę:

import com.fasterxml.jackson.databind.ObjectMapper;

Jego zależność od gradle to:

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. Korzystanie z Gson od Google

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

Importuj poniżej klasę:

import com.google.gson.Gson;

Jego ocena to:

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

Tutaj możesz pobrać poprawną zaktualizowaną wersję z repozytorium.

Md. Sajedul Karim
źródło
2

ObjectMapper.readTree() można to zrobić w jednej linii:

mapper.writerWithDefaultPrettyPrinter().writeValueAsString(mapper.readTree(json));
Praneeth
źródło
1
Powodem, dla którego podoba mi się ta odpowiedź, jest to, że nie wykonuje żadnej konwersji obiektów poza bezpośrednim mapowaniem na typy JSON. Dopóki ciąg wejściowy jest prawidłowym formatem JSON, wiemy, że ciąg wyjściowy będzie semantycznie równoważny JSON.
M. Justin