将 JsonNode 转换为 POJO

Posted

技术标签:

【中文标题】将 JsonNode 转换为 POJO【英文标题】:Convert JsonNode into POJO 【发布时间】:2013-11-11 18:20:52 【问题描述】:

这可能看起来有点不寻常,但我正在寻找一种将JsonNode 转换/映射为POJO 的有效方法。

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

我所做的是将 json 文件加载到 JsonNode 中的内存中,应用几个版本控制策略以使其与我的模型的最新版本匹配。

    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 手动应用到我的模型

【问题讨论】:

【参考方案1】:

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

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

其中jsonObjectMapper 是杰克逊ObjectMapper


在杰克逊的旧版本中,它会是

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

【讨论】:

不幸的是,没有像 readValue() 那样的 treeToValue(TreeNode n,TypeReference type) 变体。对于使用泛型处理更复杂类型的任何人来说都是个坏消息:( @Espinosa Per jackson-databind#1294,你会想要类似(不幸的是更冗长)jsonObjectMapper.readValue(jsonObjectMapper.treeAsTokens(someJsonNode), someTypeReference) 旧版本使用:objectMapper.treeToValue(jsonNode, MyClass.class) 你也可以在StdDeserializer中使用这个方法:p.codec.treeToValue @icedtrees jsonObjectMapper 是 JsonObjectMapper 的一个实例或只是 ObjectMapper【参考方案2】:

这应该可以解决问题:

mapper.readValue(fileReader, MyClass.class);

我说应该是因为我使用的是 String,而不是 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)

您还可以在实例化ObjectMapper 时定义自定义反序列化器: http://wiki.fasterxml.com/JacksonHowToCustomDeserializers

编辑: 我只是想起了另一件事。如果您传入的对象具有比 POJO 更多的属性,并且您只想忽略要设置的额外内容:

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

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

【讨论】:

我将使用 CustomDeserializers,它会为我省去很多麻烦!我还可以在其中应用我的版本控制策略,只需很少的修改。谢谢! 现在的语法是:com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper(); mapper.disable(com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); 好点@llambda!自 1.7.9 版以来我还没有接触过 ObjectMapper,看起来我的答案已经过时了几个版本。一定要检查你使用的是什么版本的 Jackson。 @EricBarr,我使用的是 Jackson v1.9.11,您答案中的语法是该版本的正确语法。也许他们试图改变并在新版本中再次恢复【参考方案3】:

如果您使用的是 org.codehaus.jackson,那么从 1.6 开始就可以做到这一点。您可以使用ObjectMapper#readValue 将 JsonNode 转换为 POJO: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);

【讨论】:

2.4.4 好像没有这个方法 查看下面的 icedtrees 的answer,了解第 2 版解决方案 文档现在位于fasterxml.github.io/jackson-databind/javadoc/2.5/com/fasterxml/…【参考方案4】:
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);

【讨论】:

以上是关于将 JsonNode 转换为 POJO的主要内容,如果未能解决你的问题,请参考以下文章

如何将 JsonNode 转换为 Map

在Jackson中将Java对象转换为JsonNode [重复]

Jackson Json:如何将数组转换为 JsonNode 和 ObjectNode?

Jackson 如何在不强制转换的情况下将 JsonNode 转换为 ArrayNode?

当前推荐的将 byte[] 转换为 JsonNode 并返回的方法

将 Map<String, String> 转换为 POJO