我需要在Java中的fastxml jackson中获取ArrayNode对象的子数组。
更清楚,
可以按照如下所示的非常原始的方式进行,
ArrayNode arrayNodeRecProducts = (ArrayNode) recProducts;
int arrayNodeSize = arrayNodeRecProducts.size();
if (limit >= 0 && limit < arrayNodeSize) {
while (arrayNodeRecProducts.has(limit)) {
arrayNodeRecProducts.remove(limit);
}
}
铸造到ArrayNode类型的“recProducts”对象是一个fastxml jackson JsonNode并包含一个数组。
以上工作但效率很低,因为内部while循环运行“arrayNodeSize - limit”逐个删除ArrayNode对象的次数。
我们可以在ArrayNode或者已经转换的JsonNode本身上执行子数组操作吗?
谢谢和问候..
答案 0 :(得分:2)
谢谢&#34; henrik&#34;对于你的答案,你说得对,杰克逊不支持ArrayNodes的这种功能。所以我所做的是我下载了Jackson数据库代码库,并查看了内部为什么他们没有为ArrayNodes提供这样的SubArray功能(请注意我是指数据绑定2.3.2)。
在内部,杰克逊将ArrayNode维护在JsonNode列表中,如下所示,
private final List<JsonNode> _children = new ArrayList<JsonNode>();
令我惊讶的是,由于某种原因我无法理解,他们没有提供SubArray操作,这可以通过使用此包含列表的subList方法轻松完成。例如,如下所示,
public List<JsonNode> subArray(int fromIndex, int toIndex) {
return _children.subList(fromIndex, toIndex);
}
上述方法可以避免我遇到的麻烦,但它根本没有包含在库中。
所以我在代码库中所做的就是在运行时使用反射破解这个私有列表,并在运行时调用subList操作,如下所示。
ArrayNode arrayNodeRecProducts = (ArrayNode) recProducts;
if (limit >= 0 && limit < arrayNodeRecProducts.size()) {
Field innerArrayNode = ArrayNode.class.getDeclaredField("_children");
innerArrayNode.setAccessible(true);
List<JsonNode> innerArrayNodeChildNodes = (List<JsonNode>) innerArrayNode.get(arrayNodeRecProducts);
List<JsonNode> limitedChildNodes = innerArrayNodeChildNodes.subList(0, limit);
innerArrayNode.set(arrayNodeRecProducts, limitedChildNodes);
}
我知道上面的代码在所有情况下都不会起作用,但对于我的情况,它工作正常。
与此同时,我知道这违反了我们保守的OO原则封装,但我可以接受这一点,原因如下文所述。
Dosen't Reflection API break the very purpose of Data encapsulation?
答案 1 :(得分:0)
杰克逊没有这样的支持。
我会创建一个新的ArrayNode并将其填充到极限,这在大多数情况下会更有效:
ArrayNode limited = objectMapper.createArrayNode();
for(JsonNode e : src) {
limited.add(e);
if (limited.size() == limit) {
break;
}
}