JSON Pretty-Print em Java


217

estou a usar e preciso imprimir dados JSON de maneira bonita (torná-los mais legíveis por humanos).

Não consegui encontrar essa funcionalidade nessa biblioteca. Como isso é comumente alcançado?

Respostas:


284

O GSON pode fazer isso de uma maneira agradável:

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

1
Bem, eu incluí o código para analisar uma string em um JsonElement, normalmente você já possui o trabalho anterior que faz com os dados JSON. Mas eu queria incluí-lo aqui para tornar o uso mais claro.
Ray Hulha

Desde que esta resposta me ajudou. Eu adicionei o código abaixo para reduzir esta declaração para menos linhas, se é isso que você está procurando. public String prettifyJson (String json) {JsonElement jsonElement = new JsonParser (). parse (json); retornar novo GsonBuilder (). setPrettyPrinting (). create (). toJson (jsonElement); }
ahmad

2
É possível responder à pergunta do OP sem precisar de bibliotecas adicionais, pois você pode simplesmente acessar o analisador JSON incorporado no Rhino (JDK 1.7 e superior). Eu não acho que é desejável adicionar uma biblioteca a um projeto apenas para formatar alguma saída de depuração. scriptEngine.eval("result = JSON.stringify(JSON.parse(jsonString), null, 2)");
Agnes

1
Em contraste com a alternativa org.json, a maneira GSON de imprimir bonita mantém a ordem dos elementos intactos após a transformação.
Aydin K.

1
Obrigado pelo ponteiro para GsonBuilder, desde que eu estava usando gson.toJson(object), simplesmente tive que mudar minha instanciação de Gson gson = new Gson();para Gson gson = new GsonBuilder().setPrettyPrinting().create(); e meu código continuou a funcionar, mas imprimiu bastante o objeto em vez de uma única linha.
cptully

153

Eu costumava org.json built-in métodos para pretty-imprimir os dados.

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

A ordem dos campos no JSON é aleatória por definição. Uma ordem específica está sujeita à implementação do analisador.


7
Também prefiro esta solução, porque você não precisa importar dependências adicionais, como sugerem outras respostas.
GDRT

3
Falta uma importação crucial - import org.json.JSONObject;
precisa saber é o seguinte

existe alguma maneira de não ter os campos em ordem aleatória, eu quero na ordem em que os adicionei?
9789 Thomas

@ThomasAdrian não é possível com org.json.JSONObject.
Raghu Kiran

O Underscore-java mantém a ordem dos atributos ao formatar o json.
Valentyn Kolesnikov

37

Parece que o GSON suporta isso, embora eu não saiba se você deseja alternar da biblioteca que está usando.

No guia do usuário:

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

4
O problema com o GSON, é complicado, o json-simple é muito mais fácil.
mabuzer

1
Não vejo esse problema há mais de um ano, mas se você quiser modificar um pouco o código-fonte, code.google.com/p/json-simple/issues/detail?id=22 possui algumas informações sobre aprimorando json-simple com pretty-printing.
BuffaloBuffalo

Tenho apenas string sem formatação de impressão bonita :(
Cherry

imprimir String com \ r \ n
Stone Jack

Obrigado. a substituição de toString () em uma linha: new GsonBuilder (). setPrettyPrinting (). create (). toJson (this);
KeepAtIt 25/01

30

Com Jackson ( com.fasterxml.jackson.databind):

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

De: como ativar a saída JSON bonita de impressão (Jackson)

Eu sei que isso já está nas respostas, mas quero escrevê-lo separadamente aqui, porque as chances são de que você já tenha Jackson como uma dependência e, portanto, tudo que você precisará seria uma linha extra de código


21

Se você estiver usando uma implementação da API Java para processamento JSON (JSR-353), poderá especificar a JsonGenerator.PRETTY_PRINTINGpropriedade ao criar um JsonGeneratorFactory.

O exemplo a seguir foi publicado originalmente no meu blog .

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

Minha situação é que meu projeto usa um analisador JSON herdado (não JSR) que não suporta impressão bonita. No entanto, eu precisava produzir amostras JSON bem impressas; isso é possível sem a necessidade de adicionar bibliotecas extras, desde que você esteja usando o Java 7 e superior:

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
Isto é impressionante, usar o motor de js para fazê-lo, de modo muito mais simples
med116

aviso se você se importa: o ScriptEngineManager não é API.
Nclark 02/11/19

18

Impressão bonita com o GSON em uma linha:

System.out.println(new GsonBuilder().setPrettyPrinting().create().toJson(new JsonParser().parse(jsonString)));

Além de inline, isso é equivalente à resposta aceita .


8

A maioria das respostas existentes depende de alguma biblioteca externa ou requer uma versão Java especial. Aqui está um código simples para imprimir uma string JSON, usando apenas APIs Java gerais (disponível no Java 7 para versões superiores; ainda não tentei a versão mais antiga).

A idéia básica é modificar a formatação com base em caracteres especiais em JSON. Por exemplo, se um '{' ou '[' for observado, o código criará uma nova linha e aumentará o nível de recuo.

Isenção de responsabilidade: testei isso apenas em alguns casos simples de JSON (par básico de valores-chave, lista, JSON aninhado); portanto, pode ser necessário algum trabalho para texto JSON mais geral, como o valor da string com aspas dentro ou caracteres especiais (\ n, \ t etc.).

/**
 * 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("  ");
  }
}

Na primeira leitura, fiquei muito descontente com essa sugestão, mas depois de ler todas as respostas, essa é a melhor solução. Pelo menos, se for apenas para alguma saída de depuração e você não desejar arrastar dependências, poderá ser removido posteriormente mais tarde. Muito obrigado!
User2081279 08/08/19

7

Em uma linha:

String niceFormattedJson = JsonWriter.formatJson(jsonString)

A biblioteca json-io ( https://github.com/jdereg/json-io ) é uma pequena biblioteca (75K) sem outras dependências além do JDK.

Além de JSON de impressão bonita, você pode serializar objetos Java (gráficos inteiros de objetos Java com ciclos) para JSON, bem como lê-los.


7

Agora isso pode ser alcançado com a biblioteca JSONLib:

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

Se (e somente se) você usar o toString(int indentationFactor)método sobrecarregado e não o toString()método padrão .

Eu verifiquei isso na seguinte versão da API:

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

3
Embora essa biblioteca possa ajudar a responder à pergunta, seria melhor incluir um exemplo de como é aplicável ao problema com algumas explicações sobre como ele funciona.
Francesco Menzani

1
Ok, obrigado pelo feedback. Embora lembre-se, pessoas como eu são voluntárias e não são pagas para fornecer um serviço que garanta o cumprimento dos padrões de qualidade. Temos tempo limitado, porque geralmente estamos no meio do trabalho ou temos deveres familiares. É por isso que "editar" está disponível para os leitores, para que possamos tornar as postagens umas das outras mais úteis.
Sridhar Sarnobat

6

Seguindo as especificações do JSON-P 1.0 ( JSR-353 ), uma solução mais atual para um determinado JsonStructure( JsonObjectou JsonArray) poderia ter a seguinte aparência:

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

Você pode usar o Gson como abaixo

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

A partir do post JSON bonita imprimir usando Gson

Como alternativa, você pode usar Jackson como abaixo

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

Do post Pretty print JSON in Java (Jackson)

Espero que esta ajuda!


4

Usando org json. Link de referência

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

Usando o Gson. Link de referência

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

Usando Jackson. Link de referência

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

Usando Genson. Link de referência .

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


0

Você pode usar a pequena biblioteca json

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

-2

Sublinhado-java tem método estático U.formatJson(json). São suportados cinco tipos de formato: 2, 3, 4, guias e compactos. Eu sou o mantenedor do projeto. Exemplo ao vivo

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

Resultado:

{
  "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"
    }
}    
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.