Conversão JsonNode em POJO


143

Isso pode parecer um pouco incomum, mas estou procurando uma maneira eficiente de transformar / mapear a JsonNodeem a POJO.

Eu armazeno algumas das informações do meu modelo em arquivos json e tenho que suportar algumas versões do meu modelo.

O que faço é carregar o arquivo json na memória em um JsonNode, aplicar algumas estratégias de versão para torná-lo compatível com a versão mais recente do meu Model.

    ObjectMapper mapper = new ObjectMapper();
    BufferedReader fileReader = new BufferedReader(new FileReader(projPath));

    JsonNode rootNode = mapper.readTree(fileReader);

    //Upgrade our file in memory
    applyVersioningStrategy(rootNode);

    ProjectModel project = mapJsonNodeToProject(rootNode);

A menos que exista uma maneira mais rápida de fazer isso, provavelmente acabarei aplicando manualmente o JsonNodesao meu Model

Respostas:


264

No Jackson 2.4, você pode converter da seguinte maneira:

MyClass newJsonNode = jsonObjectMapper.treeToValue(someJsonNode, MyClass.class);

Onde jsonObjectMapperestá um Jackson ObjectMapper?


Nas versões mais antigas de Jackson, seria

MyClass newJsonNode = jsonObjectMapper.readValue(someJsonNode, MyClass.class);

18
Infelizmente, não há variante treeToValue (TreeNode n, TypeReference <T>) como existe para readValue (). Más notícias para quem lida com tipos mais complexos com genéricos :(
Espinosa

13
@Espinosa Per jackson-databind # 1294 , você vai querer algo como (infelizmente mais detalhado)jsonObjectMapper.readValue(jsonObjectMapper.treeAsTokens(someJsonNode), someTypeReference)
M. Justin

Para versão mais antiga, use:objectMapper.treeToValue(jsonNode, MyClass.class)
amod

2
Você também pode usar esse método em StdDeserializer: p.codec.treeToValue.
Galcyurio 28/05

@icedtrees jsonObjectMapper é uma instância de JsonObjectMapper ou apenas o ObjectMapper
KNDheeraj

8

Isso deve fazer o truque:

mapper.readValue(fileReader, MyClass.class);

Eu digo que deveria, porque estou usando isso com um String, não um, BufferedReadermas ainda deve funcionar.

Aqui está o meu código:

String inputString = // I grab my string here
MySessionClass sessionObject;
try {
    ObjectMapper objectMapper = new ObjectMapper();
    sessionObject = objectMapper.readValue(inputString, MySessionClass.class);

Aqui está a documentação oficial para essa chamada: http://jackson.codehaus.org/1.7.9/javadoc/org/codehaus/jackson/map/ObjectMapper.html#readValue(java.lang.String, java.lang.Class)

Você também pode definir um desserializador personalizado ao instanciar o ObjectMapper: http://wiki.fasterxml.com/JacksonHowToCustomDeserializers

Edit: Acabei de me lembrar de outra coisa. Se o seu objeto que chega tem mais propriedades do que o POJOseu e você deseja apenas ignorar os extras, defina isso:

    objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);

Ou você receberá um erro que não consegue encontrar a propriedade para definir.


Vou usar um CustomDeserializers, isso vai me salvar muitas dores de cabeça! Também poderei aplicar minhas estratégias de versão com poucas modificações. Obrigado!
31413 Alexandre

5
A sintaxe agora é: mapeador com.fasterxml.jackson.databind.ObjectMapper = novo mapeador com.fasterxml.jackson.databind.ObjectMapper (); mapper.disable (com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
llambda

Bom ponto @llambda! Não toquei no ObjectMapper desde a versão 1.7.9, parece que minha resposta está desatualizada em algumas versões. Definitivamente, verifique qual versão do Jackson você está usando.
Eric Barr

@ EricBarr, estou usando o Jackson v1.9.11 e a sintaxe na sua resposta é a correta para essa versão. Talvez eles tentaram mudar as coisas e reverteu-los novamente nas versões mais recentes
Ivaylo Slavov

5

Se você estiver usando org.codehaus.jackson, isso é possível desde a versão 1.6. Você pode converter um JsonNode em um POJO com ObjectMapper#readValue: http://jackson.codehaus.org/1.9.4/javadoc/org/codehaus/jackson/map/ObjectMapper.html#readValue(org.codehaus.jackson.JsonNode , java. lang.Class)


    ObjectMapper mapper = new ObjectMapper();
    JsonParser jsonParser = mapper.getJsonFactory().createJsonParser("{\"foo\":\"bar\"}");
    JsonNode tree = jsonParser.readValueAsTree();
    // Do stuff to the tree
    mapper.readValue(tree, Foo.class);

5
Estes métodos parece estar faltando no 2.4.4
Kevin Wittek

1
Veja a resposta dos icedtrees abaixo, para uma solução da versão 2
Tim Büthe 4/15/15

A documentação agora está em mais rápidaxml.github.io
David Tonhofer

3
String jsonInput = "{ \"hi\": \"Assume this is the JSON\"} ";
com.fasterxml.jackson.databind.ObjectMapper mapper =
    new com.fasterxml.jackson.databind.ObjectMapper();
MyClass myObject = objectMapper.readValue(jsonInput, MyClass.class);

Se sua entrada JSON tiver mais propriedades do que seu POJO e você quiser apenas ignorar os extras no Jackson 2.4, poderá configurar seu ObjectMapper da seguinte maneira. Essa sintaxe é diferente das versões mais antigas de Jackson. (Se você usar a sintaxe errada, ela silenciosamente não fará nada.)

mapper.disable(com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNK‌​NOWN_PROPERTIES);
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.