How do I get a list of all JSON paths to values from a JSON String?

20,679

Solution 1

I came up with a solution, sharing in case anyone else is looking for the same thing:

public class JsonParser {

    private List<String> pathList;
    private String json;

    public JsonParser(String json) {
        this.json = json;
        this.pathList = new ArrayList<String>();
        setJsonPaths(json);
    }

    public List<String> getPathList() {
        return this.pathList;
    }

    private void setJsonPaths(String json) {
        this.pathList = new ArrayList<String>();
        JSONObject object = new JSONObject(json);
        String jsonPath = "$";
        if(json != JSONObject.NULL) {
            readObject(object, jsonPath);
        }   
    }

    private void readObject(JSONObject object, String jsonPath) {
        Iterator<String> keysItr = object.keys();
        String parentPath = jsonPath;
        while(keysItr.hasNext()) {
            String key = keysItr.next();
            Object value = object.get(key);
            jsonPath = parentPath + "." + key;

            if(value instanceof JSONArray) {            
                readArray((JSONArray) value, jsonPath);
            }
            else if(value instanceof JSONObject) {
                readObject((JSONObject) value, jsonPath);
            } else { // is a value
                this.pathList.add(jsonPath);    
            }          
        }  
    }

    private void readArray(JSONArray array, String jsonPath) {      
        String parentPath = jsonPath;
        for(int i = 0; i < array.length(); i++) {
            Object value = array.get(i);        
            jsonPath = parentPath + "[" + i + "]";

            if(value instanceof JSONArray) {
                readArray((JSONArray) value, jsonPath);
            } else if(value instanceof JSONObject) {                
                readObject((JSONObject) value, jsonPath);
            } else { // is a value
                this.pathList.add(jsonPath);
            }       
        }
    }

}

Solution 2

Refer to this utility : https://github.com/wnameless/json-flattener Perfect answer to your requirement. Provides Flattened map and Flattened strings for complex json strings. I am not the author of this but have used it successfully for my usecase.

Share:
20,679
yak
Author by

yak

Updated on July 09, 2022

Comments

  • yak
    yak almost 2 years

    My goal is to read a JSON file and understand the location of all the values, so that when I encounter that same JSON, I can easily read all the values. I am looking for a way to return a list containing all of the paths to each data value, in Jayway JsonPath format.

    Example JSON:

    {
      "shopper": {
        "Id": "4973860941232342",
        "Context": {
          "CollapseOrderItems": false,
          "IsTest": false
        }
      },
      "SelfIdentifiersData": {
        "SelfIdentifierData": [
          {
            "SelfIdentifierType": {
              "SelfIdentifierType": "111"
            }
          },
          {
            "SelfIdentifierType": {
              "SelfIdentifierType": "2222"
            }
          }
        ]
      }
    }
    

    Ideally I would like to take that JSON as a String and do something like this:

    String json = "{'shopper': {'Id': '4973860941232342', 'Context': {'CollapseOrderItems': false, 'IsTest': false } }, 'SelfIdentifiersData': {'SelfIdentifierData': [{'SelfIdentifierType': {'SelfIdentifierType': '111'} }, {'SelfIdentifierType': {'SelfIdentifierType': '2222'} } ] } }";
    
    Configuration conf = Configuration.defaultConfiguration();
    List<String> jsonPaths = JsonPath.using(conf).parse(json).read("$");
    
    for (String path : jsonPaths) {
        System.out.println(path);
    }
    

    This code would print this, which is the location of all values in the JSON:

    $.shopper.Id
    $.shopper.Context.CollapseOrderItems
    $.shopper.Context.IsTest
    $.SelfIdentifiersData[0].SelfIdentifierData.SelfIdentifierType.SelfIdentifierType
    $.SelfIdentifiersData[1].SelfIdentifierData.SelfIdentifierType.SelfIdentifierType
    

    Then ideally, I would be able to take that list and parse the same JSON object to get each value present.

    //after list is created
    Object document = Configuration.defaultConfiguration().jsonProvider().parse(json);
    
    for (String path : jsonPaths) {
        Object value = JsonPath.read(document, path);
        //do something
    }
    

    I am aware that I could get a Map that is a representation of the JSON file, but I am not sure that provides the same ease of access to retrieve all the values. If there is a easy way to do with JSONPath, that would be great, otherwise any other approaches are welcome.

  • Jan van Oort
    Jan van Oort over 4 years
    Very useful tip! I had a rather similar with a customer; they now use json-flattener in my (production) software.
  • Lakshmipathi G
    Lakshmipathi G almost 2 years
    Tried many solutions, but this one perfectly worked.
  • chendu
    chendu almost 2 years
    how do u import JSONOBject? and JSONArray?