获得Fasterxml Jackson ArrayNode的SubArray

时间:2015-02-24 14:20:57

标签: java arrays json jackson fasterxml

我需要在Java中的fastxml jackson中获取ArrayNode对象的子数组。

更清楚,

  1. 我有一个fastxml jackson ArrayNode对象,其中包含例如100个对象。
  2. 我有一个限制参数,例如让我们说5。
  3. 可以按照如下所示的非常原始的方式进行,

    ArrayNode arrayNodeRecProducts = (ArrayNode) recProducts;
    int arrayNodeSize = arrayNodeRecProducts.size();
    
    if (limit >= 0 && limit < arrayNodeSize) {
        while (arrayNodeRecProducts.has(limit)) {
            arrayNodeRecProducts.remove(limit);
        }
    }
    
  4. 铸造到ArrayNode类型的“recProducts”对象是一个fastxml jackson JsonNode并包含一个数组。

    以上工作但效率很低,因为内部while循环运行“arrayNodeSize - limit”逐个删除ArrayNode对象的次数。

    我们可以在ArrayNode或者已经转换的JsonNode本身上执行子数组操作吗?

    谢谢和问候..

2 个答案:

答案 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;
        }
    }