I need to get a sub-array of an ArrayNode object in fasterxml jackson in Java.
To be more clear,
Can do it in a very primitive way as indicated below,
ArrayNode arrayNodeRecProducts = (ArrayNode) recProducts;
int arrayNodeSize = arrayNodeRecProducts.size();
if (limit >= 0 && limit < arrayNodeSize) {
while (arrayNodeRecProducts.has(limit)) {
arrayNodeRecProducts.remove(limit);
}
}
The "recProducts" object casted to ArrayNode type is a fasterxml jackson JsonNode and contains an array.
Above works but quite inefficient as the inner while loop runs for "arrayNodeSize - limit" number of times in removing the ArrayNode objects one by one.
Is there a sub-array operation which we can perform on the ArrayNode or the casted JsonNode itself?
Thanks and Regards..
Thanks "henrik" for your answer and you were correct in that Jackson doesn't support such a functionality for ArrayNodes. So what I did was I downloaded the Jackson databind codebase and looked inside the hood why they are not providing such a SubArray functionality for ArrayNodes (Please be informed that I am referring to databind 2.3.2).
Internally, Jackson is maintaining the ArrayNode in a JsonNode List as below,
private final List<JsonNode> _children = new ArrayList<JsonNode>();
To my surprise, for some reason I cannot understand, they have not provided a SubArray operation which could be easily accomplished by using the subList method of this contained list. For example as below,
public List<JsonNode> subArray(int fromIndex, int toIndex) {
return _children.subList(fromIndex, toIndex);
}
Above method would have saved me from the trouble I was facing but it is simply not included in the library.
So what I did in my codebase is to simply hack into this private list in runtime using reflection and invoke the subList operation at runtime as below.
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);
}
I know that the above code will not work in all situations but for my situation it is working fine.
At the same time, I know this is a violation of our well guarded OO principle Encapsulation, but I can live with that for reasons explained in below post.
Dosen't Reflection API break the very purpose of Data encapsulation?