【问题标题】:Getting a SubArray of Fasterxml Jackson ArrayNode获取 Fasterxml Jackson ArrayNode 的子数组
【发布时间】:2015-04-26 05:14:59
【问题描述】:

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

为了更清楚,

  1. 我有一个 fasterxml 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);
        }
    }
    

转换为 ArrayNode 类型的“recProducts”对象是一个 fasterxml jackson JsonNode 并包含一个数组。

上述方法有效,但效率很低,因为内部 while 循环运行“arrayNodeSize - 限制”次数以逐个删除 ArrayNode 对象。

是否有我们可以在 ArrayNode 或被转换的 JsonNode 本身上执行的子数组操作?

感谢和问候..

【问题讨论】:

    标签: java arrays json jackson fasterxml


    【解决方案1】:

    Jackson 中没有这样的支持版本。

    我会创建一个新的 ArrayNode 并将其填充到极限,这在大多数情况下会更有效:

    ArrayNode limited = objectMapper.createArrayNode();
    for(JsonNode e : src) {
            limited.add(e);
            if (limited.size() == limit) {
                break;
            }
        }
    

    【讨论】:

    • 没错,这比我目前的效率更高,因为它只运行“限制”指定的次数。但是根据您的回答,杰克逊没有其他方法可以做到这一点吗?我什至愿意将源 JsonNode 更改为 Jackson 中可用的其他类型。感谢您的帮助。
    • 我很确定没有。您可以创建自己的实用程序类。
    • 再次感谢亨里克。但是我找到了自己的解决方案来解决我在回答中发布的具体问题。当强制性的 5 小时结束时,我会将其标记为答案,将我自己的答案标记为答案。
    【解决方案2】:

    感谢“henrik”的回答,你说得对,Jackson 不支持 ArrayNodes 的这种功能。所以我所做的是我下载了 Jackson 数据绑定代码库并深入了解为什么他们没有为 ArrayNodes 提供这样的 SubArray 功能(请注意,我指的是数据绑定 2.3.2)。

    在内部,Jackson 在 JsonNode 列表中维护 ArrayNode,如下所示,

    private final List<JsonNode> _children = new ArrayList<JsonNode>();
    

    令我惊讶的是,出于某种我无法理解的原因,他们没有提供可以通过使用此包含列表的 subList 方法轻松完成的 SubArray 操作。比如下图,

    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?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-10
      • 2017-11-26
      • 2020-11-24
      • 2015-08-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多