Конвертировать JSON String в Pretty Print JSON, используя Джексон

165

Это строка JSON, которую я имею:

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

Мне нужно преобразовать вышеупомянутый JSON Stringв вывод JSON Pretty Print (используя Джексона), как показано ниже:

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

Может ли кто-нибудь предоставить мне пример, основанный на моем примере выше? Как добиться этого сценария? Я знаю, что есть много примеров, но я не могу понять их должным образом. Любая помощь будет оценена на простом примере.

Обновлено:

Ниже приведен код, который я использую:

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

Но это не работает так, как мне нужно, как указано выше.

Вот POJO, который я использую для вышеуказанного 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;
}

Может кто-нибудь сказать мне, получил ли я правильный POJO для JSON или нет?

Обновлено:

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

Ниже строка выводит что-то вроде этого:

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

именно так мне нужно было показать. Но когда я добавляю его в модель вот так:

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

А затем показывает это на JSP-странице результирующей формы, как показано ниже:

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

    </fieldset>

Я получаю что-то вроде этого:

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

который мне не нужен. Мне нужно было, как это было напечатано выше. Может кто-нибудь сказать мне, почему это произошло таким образом?

арсенал
источник

Ответы:

252

Чтобы сделать отступ для любого старого JSON, просто свяжите его как Object:

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

а затем запишите это с отступом:

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

это избавляет вас от необходимости определять фактическое POJO для сопоставления данных.

Или вы можете использовать JsonNode(JSON Tree).

StaxMan
источник
Спасибо StaxMan, я думаю, это работает. Когда я печатаю отступ, я получаю то, что мне нужно. Но когда я использую отступ, чтобы добавить в модель, чтобы я мог показать их на странице результата. Он по-прежнему печатается в две три строки. Я обновил вопрос, может быть, вы получите больше представления о том, что происходит сейчас.
Арсенал
Тогда проблема в Spring - я предполагаю, что он ожидает POJO в качестве атрибута, а не предварительно отформатированный String. Таким образом, вместо того, чтобы пытаться отформатировать его самостоятельно, вам нужно сказать Spring, чтобы сделать это. При использовании Джексона должна быть возможность настроить его на использование отступов. Хотя, если честно, я не уверен, почему вам нужно сделать отступ для ответа.
StaxMan
30
Привет, defaultPrettyPrintingWriter () устарела. Начиная с версии 1.9, используйте взамен writerWithDefaultPrettyPrinter (). См. Jackson.codehaus.org/1.9.0/javadoc/org/codehaus/jackson/map/…
Брауни Лин
6
Для Джексона 2 используйте SerializationFeature.INDENT_OUTPUT, как указано Марсело С. ниже
Майк Р
Любая идея, как опубликовать количество письменной стоимости с использованием Джексона?
Рейанш Мишра
125

Самое простое, а также самое компактное решение (для v2.3.3):

ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
mapper.writeValueAsString(obj)
Марсело С.
источник
21
Фактически вы можете сократить это еще больше: ObjectMapper mapper = new ObjectMapper.enable (SerializationFeature.INDENT_OUTPUT);
Джейсон Николс
26

Новый способ использования Jackson 1.9+ заключается в следующем:

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

Вывод будет правильно отформатирован!

Марчелло де Сэйлс
источник
1
К сожалению, это не помогает, если мой ввод - объект, созданный во время выполнения, а не другой json.
Иннокентий
@Innokenty Тогда пропустите первую строку.
баранина
2
@muttonUp Да, конечно. Я даже сделал это, я не знаю , почему я оставил такой глупый комментарий =)
Иннокентий
17

Для Jackson 1.9, мы можем использовать следующий код для красивой печати.

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.enable(SerializationConfig.Feature.INDENT_OUTPUT);
scalauser
источник
11

Я думаю, это самый простой метод для украшения данных JSON,

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

где Response является строкой.

Просто передайте 4 (indentSpaces) в toString()методе.

Примечание: он прекрасно работает в Android без какой-либо библиотеки. Но в Java вы должны использовать библиотеку org.json .

Аман Гупта - ШОТЭР
источник
3
Стоит отметить, что это использование библиотеки JSON in Java (org.json) .
Стив Чемберс
В Android он может использовать direclty без каких-либо библиотек.
Аман Гупта - ШОТЕР
String json = new GsonBuilder().setPrettyPrinting().create().toJson(map); String indentedJson = (new JSONObject(json)).toString(4);почему-то второй теряет порядок ключей
Михаил
К сожалению, текущий подход не обрабатывает список объектов json. Я имею в виду [{"id": "1"}, {"id": "2"}]
Geniy
4

Похоже, это может быть ответом на ваш вопрос . Он говорит, что использует Spring, но я думаю, что это все равно должно помочь вам в вашем случае. Позвольте мне вставить код здесь, чтобы было удобнее:

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;}
}
Даниэль Каплан
источник
Спасибо Дэниелу за помощь. Самое сложное, что у меня есть, это как смоделировать мой JSON в классе? Если я получу эту часть работающей, я легко запишу остальную часть.
Арсенал
Можете ли вы взглянуть на мой класс POJO, который я написал из JSON? Это выглядит правильно или нет?
Арсенал
3

Вы можете добиться этого, используя следующие способы:

1. Использование Джексона из Apache

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

Класс импорта ниже:

import com.fasterxml.jackson.databind.ObjectMapper;

Это зависимость от gradle:

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. Использование Gson от Google

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

Класс импорта ниже:

import com.google.gson.Gson;

Это gradle это:

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

Здесь вы можете скачать правильную обновленную версию из репозитория.

Г-н Саджедул Карим
источник
2

ObjectMapper.readTree() можно сделать это в одну строку:

mapper.writerWithDefaultPrettyPrinter().writeValueAsString(mapper.readTree(json));
Praneeth
источник
1
Причина, по которой мне нравится этот ответ, заключается в том, что он вообще не выполняет никакого преобразования объектов, кроме прямого сопоставления с типами JSON. Пока входная строка является допустимой JSON, мы знаем, что выходная строка будет семантически эквивалентной JSON.
М. Джастин