Перетворити рядок JSON в гарненький друк 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 (за допомогою Джексона), як нижче:

{
    "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, я думаю, це працює. Коли я друкую з відступом, я отримую потрібний спосіб. Але коли я використовую відступ для додавання до Моделі, щоб я міг показати їх на сторінці результатів. Він все ще надрукується у двох трьох рядках. Я оновив питання, можливо, ви отримаєте ще трохи уявлення про те, що зараз відбувається.
арсенал

Тоді проблема з Spring - я думаю, він очікує, що атрибут POJO, а не попередньо відформатований String. Тож замість того, щоб намагатися відформатувати його самостійно, вам потрібно буде сказати Spring, щоб це зробити. Під час використання Джексона слід налаштувати його на використання відступів. Хоча, чесно кажучи, я не впевнений, чому вам навіть потрібно відступити це для відповіді.
StaxMan

30
Привіт, параметр defaultPrettyPrintingWriter () застарілий. Починаючи з 1.9, замість цього використовуйте writeWithDefaultPrettyPrinter (). Довідково
Брауні Лін

6
Для Jackson 2 використовуйте SerializationFeature.INDENT_OUTPUT, як зазначено нижче Марсело С.
Майк R

будь-яка ідея, як опублікувати кількість письмової вартості за допомогою Джексона?
Рейянш Мішра

125

Найпростіше і найбільш компактне рішення (для v2.3.3):

ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
mapper.writeValueAsString(obj)

21
Ви можете фактично скоротити це ще більше: ObjectMapper mapper = новий 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 Так, очевидно. Я навіть це зробив, я не знаю, чому я залишив такий дурний коментар =)
Innokenty

17

Для Джексона 1.9 ми можемо використовувати наступний код для гарного друку.

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

11

Я думаю, що це найпростіший прийом прикрасити дані json,

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

де Відповідь - це рядок.

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

Примітка: прекрасно працює в андроїді без будь-якої бібліотеки. Але в Java вам доведеться використовувати бібліотеку org.json .


3
Варто зауважити, що це використання бібліотеки JSON у Java (org.json) .
Стів Чемберс

В android він може використовувати direclty без будь-якої бібліотеки.
Аман Гупта - ShOoTeR

String json = new GsonBuilder().setPrettyPrinting().create().toJson(map); String indentedJson = (new JSONObject(json)).toString(4);чомусь другий втрачає порядок ключів
Михайло

Нинішній підхід, на жаль, не обробляє список об’єктів json. Я маю на увазі [{"id": "1"}, {"id": "2"}]
Геній

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;

Залежність від градуля є:

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

1
Причина, що мені подобається у цій відповіді, полягає в тому, що вона взагалі не здійснює перетворення об'єктів, крім прямого відображення у типи JSON. Поки вхідна рядок дійсна JSON, ми знаємо, що вихідна рядок буде семантично еквівалентною JSON.
М. Джастін
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.