杰克逊如何将JsonNode转换为ArrayNode而不进行转换?


116

我将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吗?是否有一种等效于的方法getJSONArrayorg.json以便在不是数组的情况下进行适当的错误处理?


不幸的是,我无法使用完整映射,因为数据无法固定字段名称。
KonradHöffner'13年

1
如果字段名称来自一组有限的名称,则您可能需要定义一个包含所有这些名称的类,并使用反序列化器的FAIL_ON_UNKNOWN_PROPERTIES功能来获取未使用的字段中返回的空值。但这当然只是字段名称设置相对有限的一种选择。
2013年

嗯,我认为此解决方案最不适合我的情况,但我会记住它,以防事先确定的有限套装出现问题!
康拉德·霍夫纳(KonradHöffner)

Answers:


247

是的,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库没有什么不同)。


2
你节省了我几个小时。谢谢!
伊戈尔·莫赖斯

我可以知道为什么在“ for(final JsonNode objNode:arrNode)”行中使用“ final”吗?
Anthony Vinay

5

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

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

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

1

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

这取决于您的输入。也就是说,您从URL中获取的内容。如果“数据集”属性的值是关联数组而不是普通数组,则将获得ClassCastException

但是同样,旧版本的正确性取决于输入。在您的新版本抛出a的情况下ClassCastException,旧版本将会抛出JSONException。参考:http : //www.json.org/javadoc/org/json/JSONObject.html#getJSONArray(java.lang.String)


好的,这样我就可以捕获ClassCastException了,谢谢!就我的口味而言,它比具有特定的JsonException优雅一些,但是如果不可能的话,那仍然不错。
康拉德·霍夫纳

0

我假设在一天结束时您想通过迭代来消耗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()) )
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.