How to filter a JSON Document using Java Stream API

Filtering through a JSON document using Java 8 Stream API involves converting the JSON document into a stream of objects and then using the filter method to select the objects that match a given condition. Here are the steps to filter through a JSON document using Java 8 Stream API.

Plain Java Streams filtering

Java Streams are wrappers around a data source, which allow us to operate with a data source, making bulk processing convenient and fast. A stream does not store data and, for this reason, is not a data structure. It also never modifies the underlying data source.

There are many usages of Java Streams API however we will show here how it can be used to filter through data. Consider the following example:

List<String> list = Arrays.asList("apple", "peach", "banana");

List<String> result = list.stream()                // convert list to stream
        .filter(line -> !"apple".equals(line))     // we exclude apple
        .collect(Collectors.toList());              // collect the output and convert streams to a List

result.forEach(System.out::println);                //output : peach banana

How can we use the same to filter a JSON Document? Let’s assume you have the following JSON Document:

{
  "name": "School ABC",
  "topics": [
    "Math",
    "Science",
    "Music",
    "History",
    "English"
  ],
  "classrooms": [
    "SectionA",
    "SectionB",
    "SectionC"
  ],
  "notes": null,
  "active": true,
  "visitors": 10000000
}

So, assumed that you have loaded your javax.json.JsonObject in a variable named ‘jsonObject’, here is how you can filter through the topics which start with ‘M’:

private JsonObject jsonObject = loadJsonObject();

public List<String> filterJsonArrayToList() {
    List<String> topics = jsonObject.getJsonArray("topics").stream()
            .filter(jsonValue -> ((JsonString) jsonValue).getString().startsWith("M"))
            .map(jsonValue -> ((JsonString) jsonValue).getString())
            .collect(Collectors.toList());
    return topics;
}

That will return a List of Strings (‘Math’,’Music’). On the other hand, if you want it as JsonArray, you can use the following code:

public JsonArray filterJsonArrayToJsonArray() {
    JsonArray topics = jsonObject.getJsonArray("topics").stream()
            .filter(jsonValue -> ((JsonString) jsonValue).getString().startsWith("C"))
            .collect(JsonCollectors.toJsonArray());
    return topics;
}

Filtering JSON with Jackson

If you want a more concise version, you can use Jackson databinding to simplify filtering JSON Data in combination with the Stream API. Let’s see a practical example of it:

///usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS com.fasterxml.jackson.core:jackson-core:2.14.2
//DEPS com.fasterxml.jackson.core:jackson-databind:2.14.2
//DEPS com.fasterxml.jackson.core:jackson-annotations:2.14.2

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

public class Main {
    public static void main(String[] args) throws Exception {
        // Example JSON document
        String jsonString = "[{\"name\": \"John\", \"age\": 30}, {\"name\": \"Jane\", \"age\": 25}, {\"name\": \"Bob\", \"age\": 35}]";
        
        // Parse the JSON document
        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode jsonNode = objectMapper.readTree(jsonString);
        
        // Convert the JSON document to a stream of objects
        Stream<JsonNode> stream = StreamSupport.stream(jsonNode.spliterator(), false);
        
        // Filter the stream of objects
        Stream<JsonNode> filteredStream = stream.filter(node -> node.get("name").asText().equals("John"));
        
        // Convert the filtered stream back to a JSON document
        JsonNode filteredJsonNode = objectMapper.valueToTree(filteredStream.collect(Collectors.toList()));
        String filteredJsonString = objectMapper.writeValueAsString(filteredJsonNode);
        
        // Print the filtered JSON document
        System.out.println(filteredJsonString);
    }
}

Firstly, we will mention that the above source code contains JBang comments so that you can run it from the shell with no project attached to it. If you are new to JBang we recommend checking this article: JBang: Create Java scripts like a pro

In this example, the main method reads in a sample JSON document as a string, parses it into a JsonNode object using the Jackson library, converts it into a stream of JsonNode objects, filters the stream to only include objects where the “name” field is equal to “John”, and then converts the filtered stream back into a JsonNode object and prints it out as a string.

You can run this class to see the filtered JSON document printed to the console.

jbang Main.java

[{"name":"John","age":30}]

Conclusion

There are several options to filter through a JSON document using Java Stream API. In this article we have covered a plain Java Stream solution and another example which uses Jackson dependencies to simplify the filtering of data

Found the article helpful? if so please follow us on Socials