Converter string JSON em saída JSON Pretty Print usando Jackson

165

Esta é a string JSON que tenho:

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

Preciso converter o JSON acima Stringna saída JSON Pretty Print (usando Jackson), como abaixo:

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

Alguém pode me fornecer um exemplo com base no meu exemplo acima? Como alcançar esse cenário? Sei que existem muitos exemplos, mas não consigo entendê-los adequadamente. Qualquer ajuda será apreciada com um exemplo simples.

Atualizada:

Abaixo está o código que estou usando:

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

Mas isso não funciona da maneira que eu precisava da saída, como mencionado acima.

Aqui está o POJO que estou usando para o JSON acima:

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

Alguém pode me dizer se eu tenho o POJO certo para o JSON ou não?

Atualizada:

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

A linha abaixo imprime algo como isto:

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

que é a maneira que eu precisava para ser mostrado. Mas quando eu adiciono ao modelo como este:

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

E então mostra isso em uma página JSP resultform como abaixo:

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

    </fieldset>

Eu recebo algo como isto:

{ "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 eu não preciso. Eu precisava da forma como foi impressa acima. Alguém pode me dizer por que aconteceu dessa maneira?

arsenal
fonte

Respostas:

252

Para recuar qualquer JSON antigo, basta vinculá-lo como Object, como:

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

e escreva-o com recuo:

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

isso evita que você precise definir o POJO real para o qual mapear os dados.

Ou você pode usar JsonNode(JSON Tree) também.

StaxMan
fonte
Obrigado StaxMan, acho que isso está funcionando. Quando imprimo recortada, fico do jeito que eu precisava. Mas quando eu uso recuado para adicionar ao modelo para que eu possa mostrá-los na página resultform. Ainda é impresso em duas três linhas. Atualizei a pergunta. Talvez você tenha mais alguma idéia do que está acontecendo agora.
arsenal
O problema está no Spring - acho que ele espera um POJO como atributo, e não uma String pré-formatada. Então, em vez de tentar formatá-lo você mesmo, precisará dizer ao Spring para fazer isso. Ao usar Jackson, deve ser possível configurá-lo para usar o recuo. Embora, para ser sincero, não sei por que você precisa recuá-lo para obter resposta.
precisa saber é
30
Olá, defaultPrettyPrintingWriter () foi preterido. Desde 1.9, use writerWithDefaultPrettyPrinter (). Consulte: jackson.codehaus.org/1.9.0/javadoc/org/codehaus/jackson/map/...
Browny Lin
6
Para o Jackson 2, use SerializationFeature.INDENT_OUTPUT, conforme especificado por Marcelo C. abaixo
Mike R
alguma idéia de como publicar a quantidade de valor escrito usando jackson?
Re
125

A solução mais simples e também a mais compacta (para v2.3.3):

ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
mapper.writeValueAsString(obj)
Marcelo C.
fonte
21
Você pode reduzir ainda mais isso: Mapeador de ObjectMapper = new ObjectMapper.enable (SerializationFeature.INDENT_OUTPUT);
Jason Nichols
26

A nova maneira de usar o Jackson 1.9+ é a seguinte:

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

A saída será formatada corretamente!

Marcello de Sales
fonte
1
Infelizmente, isso não ajuda se minha entrada for um objeto criado em tempo de execução, não outro json.
21915 Innokenty
@Innokenty Então pule a primeira linha.
muttonUp
2
@muttonUp Sim, obviamente. Eu mesmo fiz isso, eu não sei porque eu deixei um comentário tão estúpido =)
Innokenty
17

Para o Jackson 1.9, podemos usar o seguinte código para obter uma impressão bonita.

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

Eu acho que essa é a técnica mais simples de embelezar os dados do json,

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

onde Response é uma String.

Simplesmente passe os 4 (indentSpaces) no toString()método

Nota: Funciona bem no android sem nenhuma biblioteca. Mas em java, você precisa usar a biblioteca org.json .

Aman Gupta - ShOoTeR
fonte
3
Vale a pena notar que isso é usar o JSON na biblioteca Java (org.json) .
Steve Chambers
No android, ele pode usar direclty sem qualquer biblioteca.
Aman Gupta - ShOoTeR 17/08/16
String json = new GsonBuilder().setPrettyPrinting().create().toJson(map); String indentedJson = (new JSONObject(json)).toString(4);por algum motivo, o segundo é perder a ordem das chaves
Michail Michailidis
A abordagem atual, infelizmente, não trata da lista de objetos json. Quero dizer [{"id": "1"}, {"id": "2"}]
Geniy
4

Parece que pode ser a resposta para sua pergunta . Ele diz que está usando o Spring, mas acho que ainda deve ajudá-lo no seu caso. Deixe-me incorporar o código aqui, para que seja mais 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
fonte
Obrigado Daniel pela ajuda. A parte mais difícil que estou tendo é como modelar meu JSON em uma classe? Se eu conseguir essa parte funcionando, posso facilmente codificar o restante.
arsenal
Você pode dar uma olhada na minha aula de POJO que escrevi no JSON? Parece certo ou não?
arsenal
3

Você pode conseguir isso usando as seguintes maneiras:

1. Usando Jackson do Apache

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

Importar classe abaixo:

import com.fasterxml.jackson.databind.ObjectMapper;

Sua dependência gradle é:

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 o Gson do Google

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

Importar classe abaixo:

import com.google.gson.Gson;

É gradle é:

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

Aqui, você pode baixar a versão atualizada correta do repositório.

Md. Sajedul Karim
fonte
2

ObjectMapper.readTree() pode fazer isso em uma linha:

mapper.writerWithDefaultPrettyPrinter().writeValueAsString(mapper.readTree(json));
Praneeth
fonte
1
A razão de eu gostar desta resposta é que ela não realiza nenhuma conversão de objeto, exceto o mapeamento direto para tipos JSON. Desde que a string de entrada seja JSON válida, sabemos que a string de saída será JSON semanticamente equivalente.
M. Justin