深入了解 Jackson 之 JsonNode

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入了解 Jackson 之 JsonNode相关的知识,希望对你有一定的参考价值。

参考技术A Jackson JsonNode 类,完整路径为 com.fasterxml.jackson.databind.JsonNode ,是Jackson的json树模型(对象图模型)。Jackson能读 JSON 至 JsonNode 实例,写 JsonNode 到 JSON。

结果

结果的第一条可知 JsonNode 真实的实现类是 ObjectNode

JsonNode 包含一系列可以判断类型的方法

继承关系: ObjectNode <- ContainerNode<ObjectNode> <- BaseJsonNode <- JsonNode
JsonNode 是一个只读抽象类,不能直接构建 JsonNode 实例的对象图,需要创建 JsonNode 的子类 ObjectNode 实例的对象图。作为 JsonNode 的子类,ObjectNode 可以在任何使用了JsonNode之处使用。

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

【中文标题】Jackson 如何在不强制转换的情况下将 JsonNode 转换为 ArrayNode?【英文标题】:Jackson how to transform JsonNode to ArrayNode without casting? 【发布时间】:2013-05-23 04:44:54 【问题描述】:

我正在将我的 JSON 库从 org.json 更改为 Jackson,并且我想迁移以下代码:

JSONObject datasets = readJSON(new URL(DATASETS));
JSONArray datasetArray =  datasets.getJSONArray("datasets");

现在在杰克逊我有以下几点:

ObjectMapper m = new ObjectMapper();
JsonNode datasets = m.readTree(new URL(DATASETS));      
ArrayNode datasetArray = (ArrayNode)datasets.get("datasets");

但是我不喜欢那里的演员表,有没有ClassCastException 的可能性? org.json 中是否有等效于 getJSONArray 的方法,以便在它不是数组的情况下进行适当的错误处理?

【问题讨论】:

很遗憾我不能使用完整映射,因为数据没有固定字段名称。 如果字段名称来自有限的集合,您可能希望定义一个包含所有字段的类,并使用反序列化器的FAIL_ON_UNKNOWN_PROPERTIES 功能仅在未使用的字段中返回空值。但这当然只是在字段名称集相对有限的情况下的一种选择。 嗯,我认为这个解决方案不适合我的情况,但我会记住它,以防我遇到事先知道的有限集合的问题! 【参考方案1】:

org.json 中是否有与 getJSONArray 等效的方法,以便在它不是数组的情况下进行适当的错误处理?

这取决于您的输入;即您从 URL 中获取的内容。如果“datasets”属性的值是关联数组而不是普通数组,您将获得ClassCastException

不过话说回来,旧版本的正确性取决于输入。在您的新版本抛出ClassCastException 的情况下,旧版本将抛出JSONException。参考:http://www.json.org/javadoc/org/json/JSONObject.html#getJSONArray(java.lang.String)

【讨论】:

啊,好的,所以我可以捕获一个 ClassCastException,谢谢!就我的口味而言,它没有特定的 JsonException 优雅一点,但如果不可能,否则仍然很好。【参考方案2】:

是的,Jackson 手动解析器设计与其他库完全不同。特别是,您会注意到JsonNode 具有您通常会与来自其他 API 的数组节点相关联的大部分功能。因此,您无需转换为 ArrayNode 即可使用。这是一个例子:

JSON:


    "objects" : ["One", "Two", "Three"]

代码:

final String json = "\"objects\" : [\"One\", \"Two\", \"Three\"]";

final JsonNode arrNode = new ObjectMapper().readTree(json).get("objects");
if (arrNode.isArray()) 
    for (final JsonNode objNode : arrNode) 
        System.out.println(objNode);
    

输出:

“一” “二” “三”

注意在迭代之前使用isArray 来验证节点实际上是一个数组。如果您对自己的数据结构绝对有信心,则无需进行检查,但如果您需要,则可以使用它(这与大多数其他 JSON 库没有什么不同)。

【讨论】:

我可以知道为什么“for (final JsonNode objNode : arrNode)”行中使用“final”吗? @AnthonyVinay 使变量不可变;许多程序员认为这是一种很好的编码习惯。另见this讨论!【参考方案3】:

我假设最终你想通过迭代来使用 ArrayNode 中的数据。为此:

Iterator<JsonNode> iterator = datasets.withArray("datasets").elements();
while (iterator.hasNext()) 
        System.out.print(iterator.next().toString() + " "); 

或者如果您喜欢流和 lambda 函数:

import com.google.common.collect.Streams;
Streams.stream(datasets.withArray("datasets").elements())
    .forEach( item -> System.out.print(item.toString()) )

【讨论】:

【参考方案4】:

在 Java 8 中,您可以这样做:

import java.util.*;
import java.util.stream.*;

List<JsonNode> datasets = StreamSupport
    .stream(obj.get("datasets").spliterator(), false)
    .collect(Collectors.toList())

【讨论】:

我想知道他们为什么不在Spliterator 中添加stream() 方法。

以上是关于深入了解 Jackson 之 JsonNode的主要内容,如果未能解决你的问题,请参考以下文章

JSON库之性能比较:JSON.simple VS GSON VS Jackson VS JSONP

JSON库之性能比较:JSON.simple VS GSON VS Jackson VS JSONP

深入了解Qt之QObject

深入了解jQuery之整体架构

深入了解jQuery之链式结构

Memcache技术之Memcached机制深入了解