Convierta una cadena JSON en una salida JSON de Pretty Print usando Jackson

165

Esta es la cadena JSON que tengo:

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

Necesito convertir el JSON anterior Stringen Salida JSON de Pretty Print (usando Jackson), como a continuación:

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

¿Alguien puede proporcionarme un ejemplo basado en mi ejemplo anterior? ¿Cómo lograr este escenario? Sé que hay muchos ejemplos, pero no puedo entenderlos correctamente. Cualquier ayuda será apreciada con un simple ejemplo.

Actualizado:

A continuación se muestra el código que estoy usando:

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

Pero esto no funciona de la manera que necesitaba la salida como se mencionó anteriormente.

Aquí está el POJO que estoy usando para el JSON anterior:

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

¿Alguien puede decirme si obtuve el POJO correcto para el JSON o no?

Actualizado:

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

La siguiente línea imprime algo como esto:

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

así es como necesitaba que me mostraran. Pero cuando lo agrego al modelo así:

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

Y luego lo muestra en una página jsp de formulario de resultados como a continuación:

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

    </fieldset>

Me sale algo como esto:

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

que no necesito Necesitaba la forma en que se imprimió arriba. ¿Alguien puede decirme por qué sucedió de esta manera?

arsenal
fuente

Respuestas:

252

Para sangrar cualquier JSON antiguo, solo agréguelo como Object, como:

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

y luego escríbelo con sangría:

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

esto evita que tenga que definir POJO real para asignar datos.

O también puede usar JsonNode(Árbol JSON).

StaxMan
fuente
Gracias StaxMan, supongo que esto está funcionando. Cuando imprimo sangrado me interpongo en la forma que necesitaba. Pero cuando uso sangría para agregar al modelo para poder mostrarlos en la página de formulario de resultados. Todavía se imprime en dos tres líneas. He actualizado la pregunta, tal vez tenga una idea más de lo que está sucediendo ahora.
arsenal
El problema es con Spring entonces: supongo que espera un POJO como atributo, y no una cadena preformateada. Entonces, en lugar de intentar formatearlo usted mismo, deberá decirle a Spring que haga esto. Al usar Jackson, debería ser posible configurarlo para usar sangría. Aunque, para ser sincero, no estoy seguro de por qué incluso necesita sangrarlo para obtener una respuesta.
StaxMan
30
Hola, defaultPrettyPrintingWriter () ha quedado en desuso. Desde 1.9, use en su lugar writerWithDefaultPrettyPrinter (). Consulte: jackson.codehaus.org/1.9.0/javadoc/org/codehaus/jackson/map/…
Browny Lin
66
Para Jackson 2, use SerializationFeature.INDENT_OUTPUT, como lo especifica Marcelo C. a continuación
Mike R
¿Alguna idea de cómo publicar la cantidad de valor escrito con Jackson?
Reyansh Mishra
125

La solución más simple y también más compacta (para v2.3.3):

ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
mapper.writeValueAsString(obj)
Marcelo C.
fuente
21
De hecho, puede acortarlo aún más: ObjectMapper mapper = new ObjectMapper.enable (SerializationFeature.INDENT_OUTPUT);
Jason Nichols
26

La nueva forma de usar Jackson 1.9+ es la siguiente:

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

¡La salida se formateará correctamente!

Marcello de Sales
fuente
1
Desafortunadamente, eso no ayuda si mi entrada es un objeto creado en tiempo de ejecución, no otro json.
Innokenty
@Innokenty Luego omita la primera línea.
muttonUp
2
@muttonUp Sí, obviamente. Incluso lo he hecho, no sé por qué dejé un comentario tan estúpido =)
Innokenty
17

Para Jackson 1.9, podemos usar el siguiente código para una bonita impresión.

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

Creo que esta es la técnica más simple para embellecer los datos json,

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

donde Response es una cadena.

Simplemente pase el 4 (indentSpaces) en el toString()método.

Nota: Funciona bien en Android sin ninguna biblioteca. Pero en Java tienes que usar la biblioteca org.json .

Aman Gupta - ShOoTeR
fuente
3
Vale la pena señalar que esto está usando la biblioteca JSON en Java (org.json) .
Steve Chambers
En Android, puede usar direclty sin ningún libraray.
Aman Gupta - ShOoTeR
String json = new GsonBuilder().setPrettyPrinting().create().toJson(map); String indentedJson = (new JSONObject(json)).toString(4);por alguna razón, el segundo está perdiendo el orden de las llaves
Michail Michailidis
El enfoque actual, desafortunadamente, no maneja la lista de objetos json. Me refiero a [{"id": "1"}, {"id": "2"}]
Geniy
4

Parece que podría ser la respuesta a tu pregunta . Dice que está usando Spring, pero creo que eso debería ayudarte en tu caso. Permítanme incluir el código aquí para que sea más conveniente:

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;}
}
Daniel Kaplan
fuente
Gracias Daniel por la ayuda. La parte más difícil que tengo es cómo modelar mi JSON en una clase. Si hago que esa parte funcione, puedo codificar fácilmente el resto.
arsenal el
¿Puedes echar un vistazo a mi clase POJO que he escrito desde el JSON? Se ve bien o no?
arsenal el
3

Puede lograr esto de la siguiente manera:

1. Usando Jackson de Apache

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

Importar clase abajo:

import com.fasterxml.jackson.databind.ObjectMapper;

Su dependencia de Gradle es:

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. Usando Gson de Google

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

Importar clase abajo:

import com.google.gson.Gson;

Es gradle es:

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

Aquí, puede descargar la versión actualizada correcta del repositorio.

MD Sajedul Karim
fuente
2

ObjectMapper.readTree() puede hacer esto en una línea:

mapper.writerWithDefaultPrettyPrinter().writeValueAsString(mapper.readTree(json));
Praneeth
fuente
1
La razón por la que me gusta esta respuesta es que no realiza ninguna conversión de objetos que no sea la asignación directa a los tipos JSON. Mientras la cadena de entrada sea JSON válida, sabemos que la cadena de salida será JSON semánticamente equivalente.
M. Justin