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

Posted

技术标签:

【中文标题】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 转换为 ArrayNode?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不丢失信息的情况下将因子转换为整数\数字?

如何在不丢失 swift 精度的情况下将 String 转换为 Double [重复]

如何在不使用 ToString() 的情况下将 Int 转换为 C# 中的字符串?

如何在不清空 HTMLCollection 的情况下将其转换为数组?

如何在不知道格式的情况下将字符串转换为日期?

如何在不损失质量的情况下将 PNG 转换为 BMP