Симпатичний друк JSON на Java


217

Я використовую і мені потрібно сильно роздрукувати дані JSON (зробити їх більш зрозумілими для людини).

Я не зміг знайти цю функціональність у цій бібліотеці. Як це зазвичай досягається?

Відповіді:


285

GSON може це зробити приємно:

Gson gson = new GsonBuilder().setPrettyPrinting().create();
JsonParser jp = new JsonParser();
JsonElement je = jp.parse(uglyJSONString);
String prettyJsonString = gson.toJson(je);

1
Ну я включив код для розбору рядка в JsonElement, як правило, у вас це вже є в попередній роботі з даними JSON. Але я хотів включити його сюди, щоб зробити використання зрозумілішим.
Рей Хулха

Оскільки ця відповідь мені допомогла. Я додав код нижче, щоб зменшити цю заяву до меншої кількості рядків, якщо це те, що ви шукаєте. public String prettifyJson (String json) {JsonElement jsonElement = новий JsonParser (). parse (json); повернути новий GsonBuilder (). setPrettyPrinting (). create (). toJson (jsonElement); }
ахмад

2
Відповісти на питання ОП можна, не потребуючи додаткових бібліотек, оскільки ви можете просто отримати доступ до парсера JSON, вбудованого в Rhino (JDK 1.7 і вище). Я не думаю, що бажано додавати бібліотеку до проекту просто для форматування деякого налагодження. scriptEngine.eval("result = JSON.stringify(JSON.parse(jsonString), null, 2)");
Агнес

1
На відміну від альтернативи org.json, спосіб симпатичного друку GSON підтримує порядок елементів неушкодженим після трансформації.
Айдін К.

1
Дякую за вказівник на GsonBuilder, оскільки я використовував, gson.toJson(object)мені просто довелося змінити інстанцію з Gson gson = new Gson();на, Gson gson = new GsonBuilder().setPrettyPrinting().create(); і мій код продовжував працювати, але досить друкував об'єкт замість одного рядка.
cptully

153

Я використовував вбудовані методи org.json для гарного друку даних.

JSONObject json = new JSONObject(jsonString); // Convert text to object
System.out.println(json.toString(4)); // Print it with specified indentation

Порядок полів у JSON випадковий на визначення. Конкретне замовлення підлягає виконанню аналізу.


7
Я також вважаю за краще це рішення, тому що вам не потрібно імпортувати додаткові залежності, як підказують інші відповіді.
gdrt

3
Відсутній важливий імпорт - імпорт org.json.JSONObject;
MasterJoe2

чи все-таки НЕ є поля у випадковому порядку, я хочу його в тому порядку, коли я їх додав?
Томас Адріан

@ThomasAdrian неможливо з org.json.JSONObject.
Рагху Кіран

Підкреслення-java зберігає порядок атрибутів під час форматування json.
Валентин Колесніков

37

Схоже, GSON підтримує це, хоча я не знаю, чи хочете ви перейти з бібліотеки, яку ви використовуєте.

З посібника користувача:

Gson gson = new GsonBuilder().setPrettyPrinting().create();
String jsonOutput = gson.toJson(someObject);

4
Проблема з GSON, вона складна, json-simple набагато простіше.
мабузер

1
Я не розглядав цю проблему більше року, але якщо ви бажаєте трохи змінити вихідний код, code.google.com/p/json-simple/isissue/detail?id=22 містить деяку інформацію про підвищення json-простого за допомогою симпатичного друку.
BuffaloBuffalo

Отримав просто рядок без гарного форматування друку :(
Cherry

це друкувати String з \ r \ n
Stone Jack

Дякую. toString () перевизначає в одному рядку: новий GsonBuilder (). setPrettyPrinting (). create (). toJson (this);
KeepAtIt

30

З Джексоном ( com.fasterxml.jackson.databind):

ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonObject))

Від: Як увімкнути симпатичний друк JSON (Jackson)

Я знаю, що це вже є у відповідях, але я хочу написати це окремо тут, тому що швидше за все, у вас вже є Джексон як залежність, і все, що вам знадобиться, буде зайвим рядком коду


21

Якщо ви використовуєте API Java для реалізації JSON Processing (JSR-353), тоді ви можете вказати JsonGenerator.PRETTY_PRINTINGвластивість під час створення JsonGeneratorFactory.

Наступний приклад спочатку був опублікований у моїй публікації в блозі .

import java.util.*;
import javax.json.Json;
import javax.json.stream.*;

Map<String, Object> properties = new HashMap<String, Object>(1);
properties.put(JsonGenerator.PRETTY_PRINTING, true);
JsonGeneratorFactory jgf = Json.createGeneratorFactory(properties);
JsonGenerator jg = jgf.createGenerator(System.out);

jg.writeStartObject()                    // {
    .write("name", "Jane Doe")           //    "name":"Jane Doe",
    .writeStartObject("address")         //    "address":{
        .write("type", 1)                //        "type":1,
        .write("street", "1 A Street")   //        "street":"1 A Street",
        .writeNull("city")               //        "city":null,
        .write("verified", false)        //        "verified":false
    .writeEnd()                          //    },
    .writeStartArray("phone-numbers")    //    "phone-numbers":[
        .writeStartObject()              //        {
            .write("number", "555-1111") //            "number":"555-1111",
            .write("extension", "123")   //            "extension":"123"
        .writeEnd()                      //        },
        .writeStartObject()              //        {
            .write("number", "555-2222") //            "number":"555-2222",
            .writeNull("extension")      //            "extension":null
        .writeEnd()                      //        }
    .writeEnd()                          //    ]
.writeEnd()                              // }
.close();

18

Моя ситуація полягає в тому, що мій проект використовує застарілий (не-JSR) аналізатор JSON, який не підтримує гарне друкування. Однак мені потрібно було виготовити симпатичні друковані зразки JSON; це можливо без додавання додаткових бібліотек, якщо ви використовуєте Java 7 і вище:

ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine scriptEngine = manager.getEngineByName("JavaScript");
scriptEngine.put("jsonString", jsonStringNoWhitespace);
scriptEngine.eval("result = JSON.stringify(JSON.parse(jsonString), null, 2)");
String prettyPrintedJson = (String) scriptEngine.get("result");

3
Це дивовижно, використовуйте js-движок для цього, набагато простіше
med116

попередження, якщо вам все одно: ScriptEngineManager не є API.
nclark


8

Більшість наявних відповідей або залежать від зовнішньої бібліотеки, або вимагають спеціальної версії Java. Ось простий код для гарного друку рядка JSON, використовуючи лише загальні API-програми Java (доступні в Java 7 для вищих версій; хоча не пробували старішу версію).

Основна ідея - змінити форматування на основі спеціальних символів JSON. Наприклад, якщо спостерігається значення '{' або '[', код створить новий рядок і підвищить рівень відступу.

Відмова: Я тестував це лише для деяких простих випадків JSON (основна пара ключових значень, список, вкладений JSON), тому може знадобитися певна робота для більш загального тексту JSON, наприклад, значення рядка з цитатами всередині або спеціальні символи (\ n, \ т тощо).

/**
 * A simple implementation to pretty-print JSON file.
 *
 * @param unformattedJsonString
 * @return
 */
public static String prettyPrintJSON(String unformattedJsonString) {
  StringBuilder prettyJSONBuilder = new StringBuilder();
  int indentLevel = 0;
  boolean inQuote = false;
  for(char charFromUnformattedJson : unformattedJsonString.toCharArray()) {
    switch(charFromUnformattedJson) {
      case '"':
        // switch the quoting status
        inQuote = !inQuote;
        prettyJSONBuilder.append(charFromUnformattedJson);
        break;
      case ' ':
        // For space: ignore the space if it is not being quoted.
        if(inQuote) {
          prettyJSONBuilder.append(charFromUnformattedJson);
        }
        break;
      case '{':
      case '[':
        // Starting a new block: increase the indent level
        prettyJSONBuilder.append(charFromUnformattedJson);
        indentLevel++;
        appendIndentedNewLine(indentLevel, prettyJSONBuilder);
        break;
      case '}':
      case ']':
        // Ending a new block; decrese the indent level
        indentLevel--;
        appendIndentedNewLine(indentLevel, prettyJSONBuilder);
        prettyJSONBuilder.append(charFromUnformattedJson);
        break;
      case ',':
        // Ending a json item; create a new line after
        prettyJSONBuilder.append(charFromUnformattedJson);
        if(!inQuote) {
          appendIndentedNewLine(indentLevel, prettyJSONBuilder);
        }
        break;
      default:
        prettyJSONBuilder.append(charFromUnformattedJson);
    }
  }
  return prettyJSONBuilder.toString();
}

/**
 * Print a new line with indention at the beginning of the new line.
 * @param indentLevel
 * @param stringBuilder
 */
private static void appendIndentedNewLine(int indentLevel, StringBuilder stringBuilder) {
  stringBuilder.append("\n");
  for(int i = 0; i < indentLevel; i++) {
    // Assuming indention using 2 spaces
    stringBuilder.append("  ");
  }
}

На першому читанні я був дуже незадоволений цією пропозицією, але, прочитавши всі відповіді, це найкраще рішення. Принаймні, якщо це стосується лише певного виводу налагодження, і ви не хочете перетягувати залежності, ви, можливо, захочете видалити їх згодом знову. Велике спасибі!
користувач2081279

7

В одному рядку:

String niceFormattedJson = JsonWriter.formatJson(jsonString)

Бібліотека json-io ( https://github.com/jdereg/json-io ) - це невелика (75 К) бібліотека, що не має інших залежностей, ніж JDK.

Крім симпатичного друку JSON, ви можете серіалізувати об’єкти Java (цілі графіки об’єктів Java з циклами) до JSON, а також прочитати їх у.


7

Тепер цього можна досягти за допомогою бібліотеки JSONLib:

http://json-lib.sourceforge.net/apidocs/net/sf/json/JSONObject.html

Якщо (і лише якщо) ви використовуєте перевантажений toString(int indentationFactor)метод, а не стандартний toString()метод.

Я підтвердив це в наступній версії API:

<dependency>
  <groupId>org.json</groupId>
  <artifactId>json</artifactId>
  <version>20140107</version>
</dependency>

3
Хоча ця бібліотека може допомогти відповісти на питання, було б краще включити приклад того, як вона застосовна до проблеми, з деякими поясненнями щодо того, як вона працює.
Франческо Мензані

1
Добре дякую за відгуки. Хоча пам’ятайте, такі люди, як я, є волонтерами і не отримують плату за надання послуги, яка гарантує відповідність стандартам якості. У нас обмежений час, тому що ми часто перебуваємо в середині роботи або маємо сімейні обов'язки. Ось чому "редагування" доступне для читачів, тому ми можемо зробити повідомлення один одного більш корисними.
Шрідхар Сарнобат

6

Після специфікації JSON-P 1.0 ( JSR-353 ) більш сучасне рішення для даного JsonStructure( JsonObjectабо JsonArray) може виглядати так:

import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;

import javax.json.Json;
import javax.json.JsonStructure;
import javax.json.JsonWriter;
import javax.json.JsonWriterFactory;
import javax.json.stream.JsonGenerator;

public class PrettyJson {

    private static JsonWriterFactory FACTORY_INSTANCE;

    public static String toString(final JsonStructure status) {

        final StringWriter stringWriter = new StringWriter();

        final JsonWriter jsonWriter = getPrettyJsonWriterFactory()
                .createWriter(stringWriter);

        jsonWriter.write(status);
        jsonWriter.close();

        return stringWriter.toString();
    }

    private static JsonWriterFactory getPrettyJsonWriterFactory() {
        if (null == FACTORY_INSTANCE) {
            final Map<String, Object> properties = new HashMap<>(1);
            properties.put(JsonGenerator.PRETTY_PRINTING, true);
            FACTORY_INSTANCE = Json.createWriterFactory(properties);
        }
        return FACTORY_INSTANCE;
    }

}


5

Ви можете використовувати Gson як нижче

Gson gson = new GsonBuilder().setPrettyPrinting().create();
String jsonString = gson.toJson(object);

З поста JSON гарненький друк за допомогою Gson

Як варіант, ви можете використовувати Джексона, як показано нижче

ObjectMapper mapper = new ObjectMapper();
String perttyStr = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(object);

З поста Симпатичний принт JSON на Java (Джексон)

Сподіваюся, що це допоможе!


4

Використання org json. Посилання на посилання

JSONObject jsonObject = new JSONObject(obj);
String prettyJson = jsonObject.toString(4);

Використання Gson. Посилання на посилання

Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(obj);

Використання Джексона. Посилання на посилання

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

Використання Генсона. Посилання на посилання .

Genson prettyGenson = new GensonBuilder().useIndentation(true).create();
String prettyJson = prettyGenson.serialize(obj);

1

Це працювало для мене, використовуючи Джексона:

mapper.writerWithDefaultPrettyPrinter().writeValueAsString(JSONString)

Звідки це mapperвзялося?
Сердж

0

Ви можете використовувати невелику бібліотеку json

String jsonstring = ....;
JsonValue json = JsonParser.parse(jsonstring);
String jsonIndendedByTwoSpaces = json.toPrettyString("  ");

-2

Підкреслення-ява має статичний метод U.formatJson(json). Підтримуються п'ять типів формату: 2, 3, 4, вкладки та компактні. Я організатор проекту. Живий приклад

import com.github.underscore.lodash.U;

import static com.github.underscore.lodash.Json.JsonStringBuilder.Step.TABS;
import static com.github.underscore.lodash.Json.JsonStringBuilder.Step.TWO_SPACES;

public class MyClass {

    public static void main(String args[]) {
        String json = "{\"Price\": {"
        + "    \"LineItems\": {"
        + "        \"LineItem\": {"
        + "            \"UnitOfMeasure\": \"EACH\", \"Quantity\": 2, \"ItemID\": \"ItemID\""
        + "        }"
        + "    },"
        + "    \"Currency\": \"USD\","
        + "    \"EnterpriseCode\": \"EnterpriseCode\""
        + "}}";
        System.out.println(U.formatJson(json, TWO_SPACES)); 
        System.out.println(U.formatJson(json, TABS)); 
    }
}

Вихід:

{
  "Price": {
    "LineItems": {
      "LineItem": {
        "UnitOfMeasure": "EACH",
        "Quantity": 2,
        "ItemID": "ItemID"
      }
    },
    "Currency": "USD",
    "EnterpriseCode": "EnterpriseCode"
  }
}
{
    "Price": {
        "LineItems": {
            "LineItem": {
                "UnitOfMeasure": "EACH",
                "Quantity": 2,
                "ItemID": "ItemID"
            }
        },
        "Currency": "USD",
        "EnterpriseCode": "EnterpriseCode"
    }
}    
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.