Pretty-Print JSON en Java

217

Estoy usando y necesito imprimir bastante datos JSON (hacerlo más legible para los humanos).

No he podido encontrar esta funcionalidad dentro de esa biblioteca. ¿Cómo se logra esto comúnmente?

mabuzer
fuente

Respuestas:

284

GSON puede hacer esto de una manera agradable:

Gson gson = new GsonBuilder().setPrettyPrinting().create();
JsonParser jp = new JsonParser();
JsonElement je = jp.parse(uglyJSONString);
String prettyJsonString = gson.toJson(je);
Ray Hulha
fuente
1
Bueno, incluí código para analizar una cadena en un JsonElement, por lo general ya lo tienes del trabajo anterior que haces con los datos JSON. Pero quería incluirlo aquí para aclarar el uso.
Ray Hulha
Ya que esta respuesta me ayudó. He agregado el código a continuación para reducir esta declaración a menos líneas si esto es lo que está buscando. public String prettifyJson (String json) {JsonElement jsonElement = new JsonParser (). parse (json); devolver nuevo GsonBuilder (). setPrettyPrinting (). create (). toJson (jsonElement); }
ahmad
2
Es posible responder a la pregunta del OP sin necesidad de bibliotecas adicionales, ya que simplemente puede acceder al analizador JSON integrado en Rhino (JDK 1.7 y superior). No creo que sea deseable agregar una biblioteca a un proyecto solo para formatear alguna salida de depuración. scriptEngine.eval("result = JSON.stringify(JSON.parse(jsonString), null, 2)");
Agnes
1
A diferencia de la alternativa org.json, la forma GSON de impresión bonita mantiene el orden de los elementos intactos después de la transformación.
Aydin K.
1
Gracias por el puntero a GsonBuilder, ya que estaba usando gson.toJson(object), simplemente tuve que cambiar mi instanciación de Gson gson = new Gson();a Gson gson = new GsonBuilder().setPrettyPrinting().create(); y mi código continuó funcionando pero imprimí bastante el objeto en lugar de una sola línea.
cptully
153

Utilicé los métodos integrados de org.json para imprimir los datos de manera bonita.

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

El orden de los campos en JSON es aleatorio por definición. Un pedido específico está sujeto a la implementación del analizador.

Raghu Kiran
fuente
77
También prefiero esta solución, porque no necesita importar dependencias adicionales como sugieren otras respuestas.
gdrt
3
Falta una importación crucial: import org.json.JSONObject;
MasterJoe2
¿hay alguna forma de NO tener los campos en orden aleatorio, lo quiero en el orden en que los agregué?
Thomas Adrian el
@ThomasAdrian no es posible con org.json.JSONObject.
Raghu Kiran
Underscore-java mantiene el orden de los atributos mientras formatea json.
Valentyn Kolesnikov
37

Parece que GSON admite esto, aunque no sé si desea cambiar de la biblioteca que está utilizando.

De la guía del usuario:

Gson gson = new GsonBuilder().setPrettyPrinting().create();
String jsonOutput = gson.toJson(someObject);
BuffaloBuffalo
fuente
44
El problema con GSON, es complicado, json-simple es mucho más fácil.
mabuzer el
1
No he visto este problema en más de un año, pero si está dispuesto a modificar un poco el código fuente, code.google.com/p/json-simple/issues/detail?id=22 tiene información sobre mejorando json-simple con bonita impresión.
BuffaloBuffalo
Solo tengo una cadena sin ningún formato de impresión bonito :(
Cherry
imprime Cadena con \ r \ n
Stone Jack
Gracias. anulación de toString () en una línea: nuevo GsonBuilder (). setPrettyPrinting (). create (). toJson (this);
KeepAtIt
30

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

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

De: Cómo habilitar la salida JSON de impresión bonita (Jackson)

Sé que esto ya está en las respuestas, pero quiero escribirlo por separado aquí porque lo más probable es que ya tengas a Jackson como dependencia, por lo que todo lo que necesitarás sería una línea de código adicional

oktieh
fuente
21

Si está utilizando una API Java para la implementación del procesamiento JSON (JSR-353), puede especificar la JsonGenerator.PRETTY_PRINTINGpropiedad cuando cree un JsonGeneratorFactory.

El siguiente ejemplo ha sido publicado originalmente en mi 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();
bdoughan
fuente
18

Mi situación es que mi proyecto utiliza un analizador JSON heredado (no JSR) que no admite una impresión bonita. Sin embargo, necesitaba producir muestras JSON bien impresas; Esto es posible sin tener que agregar bibliotecas adicionales siempre que esté utilizando Java 7 y 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");
Inés
fuente
3
Esto es impresionante, use el motor js para hacerlo, mucho más simple
med116
advertencia si te importa: el ScriptEngineManager no es API.
nclark
18

Impresión bonita con GSON en una línea:

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

Además de en línea, esto es equivalente a la respuesta aceptada .

Bengt
fuente
8

La mayoría de las respuestas existentes dependen de alguna biblioteca externa o requieren una versión especial de Java. Aquí hay un código simple para imprimir bastante una cadena JSON, solo usando las API generales de Java (disponibles en Java 7 para versiones superiores; aunque no he probado una versión anterior).

La idea básica es activar el formato basado en caracteres especiales en JSON. Por ejemplo, si se observa un '{' o '[', el código creará una nueva línea y aumentará el nivel de sangría.

Descargo de responsabilidad: solo probé esto para algunos casos JSON simples (par clave-valor básico, lista, JSON anidado), por lo que puede necesitar algo de trabajo para texto JSON más general, como valor de cadena con comillas dentro o caracteres especiales (\ 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("  ");
  }
}
preguntaw0rder
fuente
En la primera lectura, estaba muy disgustado con esta sugerencia, pero después de leer todas las respuestas, esta es la mejor solución. Al menos, si es solo para algunos resultados de depuración, y no desea arrastrar dependencias, es posible que desee eliminar más tarde nuevamente. ¡Muchas gracias!
user2081279
7

En una linea:

String niceFormattedJson = JsonWriter.formatJson(jsonString)

El json-io libray ( https://github.com/jdereg/json-io ) es una biblioteca pequeña (75K) sin otras dependencias que el JDK.

Además de JSON de impresión bonita, puede serializar objetos Java (gráficos de objetos Java completos con ciclos) a JSON, así como leerlos.

John DeRegnaucourt
fuente
7

Ahora esto se puede lograr con la biblioteca JSONLib:

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

Si (y solo si) usa el toString(int indentationFactor)método sobrecargado y no el toString()método estándar .

He verificado esto en la siguiente versión de la API:

<dependency>
  <groupId>org.json</groupId>
  <artifactId>json</artifactId>
  <version>20140107</version>
</dependency>
Sridhar Sarnobat
fuente
3
Si bien esta biblioteca puede ayudar a responder la pregunta, sería mejor incluir un ejemplo de cómo es aplicable al problema con alguna explicación sobre cómo funciona.
Francesco Menzani
1
Ok, gracias por los comentarios. Aunque recuerde, las personas como yo somos voluntarios y no nos pagan por brindar un servicio que garantice el cumplimiento de los estándares de calidad. Tenemos tiempo limitado porque a menudo estamos en la mitad del trabajo o tenemos deberes familiares. Es por eso que "editar" está disponible para los lectores, para que podamos hacer que las publicaciones de los demás sean más útiles.
Sridhar Sarnobat
6

Siguiendo las especificaciones JSON-P 1.0 ( JSR-353 ), una solución más actual para un determinado JsonStructure( JsonObjecto JsonArray) podría verse así:

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

}
Jens Piegsa
fuente
6

En JSONLib puedes usar esto:

String jsonTxt = JSONUtils.valueToString(json, 8, 4);

Del Javadoc :

Enrique San Martín
fuente
5

Puedes usar Gson como a continuación

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

De la publicación JSON bonita impresión usando Gson

Alternativamente, puede usar Jackson como a continuación

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

De la publicación Pretty print JSON en Java (Jackson)

¡Espero que esto ayude!

David Pham
fuente
4

Usando org json. Enlace de referencia

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

Usando Gson. Enlace de referencia

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

Usando Jackson. Enlace de referencia

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

Usando Genson. Referencia enlace .

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

Esto funcionó para mí, usando Jackson:

mapper.writerWithDefaultPrettyPrinter().writeValueAsString(JSONString)
ObiWanKenobi
fuente
¿De dónde mappervino esto ?
Sertage
0

Puedes usar la pequeña biblioteca json

String jsonstring = ....;
JsonValue json = JsonParser.parse(jsonstring);
String jsonIndendedByTwoSpaces = json.toPrettyString("  ");
Anton Straka
fuente
-2

Underscore-java tiene un método estático U.formatJson(json). Se admiten cinco tipos de formatos: 2, 3, 4, pestañas y compactos. Soy el mantenedor del proyecto. Ejemplo en 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)); 
    }
}

Salida:

{
  "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"
    }
}    
Valentyn Kolesnikov
fuente