4

I'm parsing a json using Jackson's JsonNode. My json structure looks like this (let this be variable rawJson):

{
    <some fields...>,
    "results" : [
            {
                "name" : "name1",
                "data" : ...,
                "values" : 13
            }, 
            {
                "name" : "name2",
                "data" : ...,
                "values" : 20
            },
            .
            .
            .
            {
                "name" : "name_n",
                "data" : ...,
                "values" : 151
            }
        ]
}

in Java:

ObjectMapper mapper = new ObjectMapper();
JsonNode results = mapper.readValue(rawJson, JsonNode.class).get("results");

How can I get the particular JsonNode element by filtering the attribute name? How about if I want to get JsonNode elements whose value greater than X? Can I accomplish these without looping through the results variable?

1 Answer 1

3

You can use forEach(Consumer c) (JDK 1.8+) function of java.lang.Iterable to perform list iteration. This method takes a Consumer instance which process all the values in the list. This approach can be extended to take a filter while iterating as shown below:

public static void main(String[] args) {

    ObjectMapper om = new ObjectMapper();
    InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("test.json");
    try {
        JsonNode node = om.readValue(in, JsonNode.class).get("results");
        NodeFilteringConsumer consumer = new NodeFilteringConsumer(new NodeFilter() {

            @Override
            public boolean apply(JsonNode node) {
                //Filter for node with values greater than 20.
                return node.get("values").asDouble() > 20;
            }
        });

        node.forEach(consumer);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public static interface NodeFilter{

    boolean apply(JsonNode node);
}

public static class NodeFilteringConsumer implements Consumer<JsonNode>{

    private NodeFilter f;

    public NodeFilteringConsumer(NodeFilter f) {
        this.f = f;
    }


    @Override
    public void accept(JsonNode t) {
        if (f.apply(t)){
            //Only filtered records reach here
            System.out.println("Filter applied on node:" + t);
        }
    }

}
Sign up to request clarification or add additional context in comments.

3 Comments

I'm restricted to Java 7 for the meantime.
In such case, I think you will have to write a for each loop for iterating all JSONNode of results. You can re-use the NodeFilter interface though inside the for loop.
this solution does not prevent Jackson from having to parse the entire payload. Perhaps this is what the OP wanted, so not saying it's a bad answer but I was actually looking for "how to skip the actual parsing of data when a certain condition does not hold" (this is particularly useful for huge JSON files)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.