Skip to content

Searching Trees

Jan Bernitt edited this page Jan 25, 2024 · 2 revisions

Warning

The documentation below has not been updated to the newest version

As the JsonValue represents a virtual or expected tree the API to search this tree is quite limited as any search has to build upon the JsonNode API which reflects the actual tree.

For convenience the subtree of a JsonObject can be searched for an object node that satisfies a particular shape and test Predicate:

JsonObject match = root.find(JsonPasswordValidation.class, obj -> true);

The above example finds the first object in the subtree that successfully can be "cast" to a JsonPasswordValidation object, meaning it has all its @Expected members (same as calling obj.isA(JsonPasswordValidation.class) on each potential object in the subtree).

JsonObject match = root.find(JsonPasswordValidation.class, validation -> !validation.isValidPassword());

In the second example the search is extended by an additional Predicate. Now the match is the first JsonPasswordValidation which has an invalid password.

The JsonObject#find method builds upon the JsonNode API which offers a broader range of search capabilities.

  • JsonNode#find: find first match that satisfy both a particular JsonNodeType and a Predicate<JsonNode>
  • JsonNode#count: count all matches that satisfy both a particular JsonNodeType and Predicate<JsonNode>
  • JsonNode#visit: fully generic subtree visitor in form of a Consumer<JsonNode>

The downside of the JsonNode search API is that dealing with JsonNode is more cumbersome and can throw exceptions. Therefore, it can make sense to implement specific search methods similar to JsonObject#find in types that extend JsonObject.

Searching for an element in a JsonList can be done using a number of methods:

  • containsAll: check if the list contains a subset
  • contains: check at least one matching element is contained
  • containsUnique: check that one and only one matching element is contained
  • count: count elements matching a Predicate test
  • first: find the first matching element

These can be used with JsonArray as any array can be treated as list using array.asList(JsonValue.class).

Another way to test qualities of a JsonList is to use one of its toList methods to turn it into a java.util.List. The assumption is that the values in that target list should not be instances of JsonValue but "usual" java types. Therefore, any of the toList methods accepts a Function to transform the JsonValue elements into some java type. At the point of conversion the virtual tree is accessing the actual tree which means exceptions are possible. To mitigate this risk there are different variations of the toList method:

  • toList(Function): map and expect all source values to exist, otherwise throws exception
  • toList(Function, Object): map and use provided default value in case source element does not exist
  • toListOfElementsThatExists(Function): map and skip those source elements of the list that do not exist

A reason for elements to not exist in an existing array are view transformations. For example if the original elements are objects and a member is extracted for the view not all object might have this member.

Clone this wiki locally