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# 中的字符串?