将JsonNode转换成POJO


143

这似乎有点不正常,但我在寻找一个有效的方式来变换/映射JsonNodePOJO

我将模型的一些信息存储在json文件中,并且我必须支持模型的几个版本。

我要做的是将json文件加载到JsonNode的内存中,应用一些版本控制策略以使其与我的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);

除非有更快的方法,否则我可能最终将手动将其JsonNodes应用于模型

Answers:


264

在Jackson 2.4中,可以进行如下转换:

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

jsonObjectMapper杰克逊在哪儿ObjectMapper


在旧版的Jackson中,

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

18
不幸的是,没有像readValue()那样的treeToValue(TreeNode n,TypeReference <T> type)变体。对于任何使用泛型处理更复杂类型的人来说都是一个坏消息:(
Espinosa

13
@Espinosa Per jackson-databind#1294,您想要的东西(不幸的是更冗长)jsonObjectMapper.readValue(jsonObjectMapper.treeAsTokens(someJsonNode), someTypeReference)
M. Justin

对于旧版本,请使用:objectMapper.treeToValue(jsonNode, MyClass.class)
修改

2
您也可以在StdDeserializer中使用此方法:p.codec.treeToValue
galcyurio

@icedtrees jsonObjectMapper是JsonObjectMapper的实例,或者只是ObjectMapper的实例
KNDheeraj

8

这应该可以解决问题:

mapper.readValue(fileReader, MyClass.class);

我说应该,因为我使用的是String,而不是a,BufferedReader但它仍然可以正常工作。

这是我的代码:

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

这是该呼叫的官方文档:http : //jackson.codehaus.org/1.7.9/javadoc/org/codehaus/jackson/map/ObjectMapper.html#readValue(java.lang.String,java.lang.Class)

实例化以下代码时,您还可以定义自定义反序列化器ObjectMapperhttp : //wiki.fasterxml.com/JacksonHowToCustomDeserializers

编辑:我只是想起了别的东西。如果您输入的对象具有比属性更多的属性,POJO而您只想忽略其他属性,则可以设置以下内容:

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

否则,您会得到一个错误,它找不到要设置的属性。


我将使用CustomDeserializers,它将为我省去很多麻烦!只需很少的修改,我就可以在其中应用我的版本控制策略。谢谢!
2013年

5
现在的语法为:com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper(); mapper.disable(com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
llambda 2014年

好点@llambda!从1.7.9版开始,我还没有接触过ObjectMapper,看来我的答案已经过时了。绝对检查您使用的是什么版本的Jackson。
埃里克·巴尔

@EricBarr,我使用的是Jackson v1.9.11,答案中的语法是该版本的正确语法。也许他们想改变的事情,并在新版本又恢复了他们
Ivaylo Slavov

5

如果您使用的是org.codehaus.jackson,则从1.6开始就可以实现。您可以使用以下代码将JsonNode转换为POJO ObjectMapper#readValuehttp : //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
2.4.4中似乎缺少此方法
Kevin Wittek,2015年

1
见icedtrees' 答案下面,对第2版的解决方案
蒂姆·布泰


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

如果您输入的JSON输入具有比POJO更多的属性,并且您只想忽略Jackson 2.4中的附加功能,则可以按以下方式配置ObjectMapper。此语法与早期的Jackson版本不同。(如果使用错误的语法,它将无提示地执行任何操作。)

mapper.disable(com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNK‌​NOWN_PROPERTIES);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.