skip to Main Content

I have the following json file test.json

{
  "type" : "object",
  "id" : "123",
  "title" : "Test",
  "properties" : {
    "_picnic" : {
      "type" : "boolean"
....

I am able to get the first level value of the key using the following code. E.g. for type I get object

public static void main(String[] args){

        String exampleRequest = null;
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            exampleRequest = FileUtils.readFileToString(new File("src/main/resources/test.json"), StandardCharsets.UTF_8);
            JsonNode jsonNode = objectMapper.readTree(exampleRequest);

            String type = jsonNode.get("type").asText();
            System.out.println(type);

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        // System.out.println(exampleRequest);


    }

However I do not get any response when I try to get the value for the second level. E.g. if I do

String type = jsonNode.get("_picnic").asText();
System.out.println(type);

OR the whole object e.g.

String type = jsonNode.get("properties").asText();
System.out.println(type);

I tried doing properties._picnic or properties[0]_picnic but no luck.

2

Answers


  1. The documentation for that method states (emphasis mine):

    Method that will return a valid String representation of the container value, if the node is a value node (method isValueNode() returns true), otherwise empty String.

    Per the snippet of json text you shared, both "properties" and "_picnic" are objects not values so you are getting an empty string. It seems you’d need to use the get method:

    jsonNode.get("properties").get("_picnic").get("type").asText()
    
    Login or Signup to reply.
  2. You can use recursion to simplify this code. Just call getText with a starting node and a variable list (array) of paths. It will determine if it need to check for object or array.

    import java.io.*;
    import java.nio.charset.StandardCharsets;
    import org.apache.commons.io.FileUtils;
    import com.fasterxml.jackson.databind.*;
    
    public class NestedJson {
        public static void main(String[] args) {
            String exampleRequest = null;
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                exampleRequest = FileUtils.readFileToString(new File("src/main/resources/test.json"),
                        StandardCharsets.UTF_8);
                JsonNode jsonNode = objectMapper.readTree(exampleRequest);
                System.out.println(getText(jsonNode, "type")); // object
                System.out.println(getText(jsonNode, "properties", "_picnic", "type")); // boolean
                System.out.println(getText(jsonNode, "stuff", "0", "foo")); // bar
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    
        public static String getText(JsonNode node, String... path) {
            return getText(node, 0, path);
        }
    
        private static String getText(JsonNode node, int cursor, String[] path) {
            if (node == null || path == null || path.length == 0)
                return null;
            if (cursor == path.length) {
                return node != null ? node.asText() : null;
            }
            if (node.isObject()) {
                return getText(node.get(path[cursor]), cursor + 1, path);
            } else if (node.isArray()) {
                return getText(node.get(Integer.parseInt(path[cursor])), cursor + 1, path);
            }
            return null;
        }
    }
    

    Modified test.json:

    {
      "type": "object",
      "id": "123",
      "title": "Test",
      "properties": {
        "_picnic": {
          "type": "boolean"
        }
      },
      "stuff": [
        {
          "foo": "bar"
        }
      ]
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search