SharadxDutta
SharadxDutta

Reputation: 1128

Flattening multidimensional JSON in JAVA

I have a JSON which looks like this,

{
  "users": [
    {
      "displayName": "Sharad Dutta",
      "givenName": "",
      "surname": "",
      "extension_user_type": "user",
      "identities": [
        {
          "signInType": "emailAddress",
          "issuerAssignedId": "[email protected]"
        }
      ],
      "extension_timezone": "VET",
      "extension_locale": "en-GB",
      "extension_tenant": "EG12345"
    },   
    {
      "displayName": "Sharad Dutta",
      "givenName": "",
      "surname": "",
      "extension_user_type": "user",
      "identities": [
        {
          "signInType": "emailAddress",
          "issuerAssignedId": "[email protected]"
        }
      ],
      "extension_timezone": "VET",
      "extension_locale": "en-GB",
      "extension_tenant": "EG12345"
    }
  ]
}

I am writing a Java code where I am parsing this Multidimensional JSON to FLAT JSON. If you look closely, the JSON is wrapped in a "users" wrapper and then has couple of users as objects. For each user, there is a field called "identifiers" which is again a wrapper.

I want to flat this JSON, I have written a code but it is leaving a JSON blob for identifiers, for non nested it is working fine

JSONObject output;
        try {
            output = new JSONObject(userJsonAsString);
            JSONArray docs = output.getJSONArray("users");
            System.out.println(docs);

This is giving me below output, however i still have to flat inner wrapper "identifiers"

[
  {
    "extension_timezone": "VET",
    "extension_tenant": "EG12345",
    "extension_locale": "en-GB",
    "identities": [
      {
        "signInType": "emailAddress",
        "issuerAssignedId": "[email protected]"
      }
    ],
    "displayName": "Sharad Dutta",
    "surname": "",
    "givenName": "",
    "extension_user_type": "user"
  },
  {
    "extension_timezone": "VET",
    "extension_tenant": "EG12345",
    "extension_locale": "en-GB",
    "identities": [
      {
        "signInType": "userName",
        "issuerAssignedId": "pdhongade007"
      }
    ],
    "displayName": "Wayne Rooney",
    "surname": "Rooney",
    "givenName": "Wayne",
    "extension_user_type": "user"
  }
]

This is what I need,

{
    "extension_timezone": "VET",
    "extension_tenant": "EG12345",
    "extension_locale": "en-GB",
    "signInType": "emailAddress",
    "issuerAssignedId": "[email protected]",
    "displayName": "Sharad Dutta",
    "surname": "",
    "givenName": "",
    "extension_user_type": "user"
  }

I have to then parse this to CSV, which I know how, I just need to flat this further. Any help will be appreciated. I tried looking around, but a lot of them were using external dependencies.

//UPDATE

{
  "extension_timezone": "VET",
  "extension_tenant": "EG12345",
  "extension_locale": "en-GB",
  "signInType": "userName",
  "displayName": "Wayne Rooney",
  "surname": "Rooney",
  "givenName": "Wayne",
  "issuerAssignedId": "pdhongade007",
  "extension_user_type": "user"
}

When I tried @Jakub solution, I am getting the flat JSON, however it is not iterating for all the users. Just one!(I am guessing the last user only)

Upvotes: 1

Views: 533

Answers (2)

horizon
horizon

Reputation: 503

Please try the below approach, this will give you a comma separated format for both user and identifier (flat file per se),

 public static void main(String[] args) throws JSONException, ParseException {
    
            String userJsonFile = "path to your JSON";
            final StringBuilder sBuild = new StringBuilder();
            final StringBuilder sBuild2 = new StringBuilder();
            
            try {
                String userJsonAsString = convert your JSON to string and store in var;
            } catch (Exception e1) {
                e1.printStackTrace();
            }
            JSONParser jsonParser = new JSONParser();
            JSONObject output = (JSONObject) jsonParser.parse(userJsonAsString);
            try {
                
                JSONArray docs = (JSONArray) output.get("users");
                Iterator<Object> iterator = docs.iterator();
                
                
                while (iterator.hasNext()) {
                    JSONObject userEleObj = (JSONObject)iterator.next();
                    JSONArray nestedIdArray = (JSONArray) userEleObj.get("identities");
                    Iterator<Object> nestIter = nestedIdArray.iterator();
                     
                    while (nestIter.hasNext()) {
                        JSONObject identityEleObj = (JSONObject)nestIter.next(); 
                        identityEleObj.keySet().stream().forEach(key -> sBuild2.append(identityEleObj.get(key) + ","));
                        userEleObj.keySet().stream().forEach(key -> {
                            if (StringUtils.equals((CharSequence) key, "identities")) {
                                sBuild.append(sBuild2.toString());
                                sBuild2.replace(0, sBuild2.length(), "");
                            } else {
                                sBuild.append(userEleObj.get(key) + ","); 
                            }
                                
                        });
                         
                    }
                    sBuild.replace(sBuild.lastIndexOf(","), sBuild.length(), "\n");  
                }
                
                System.out.println(sBuild);
                
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

Upvotes: 1

Jakub
Jakub

Reputation: 11

You can traverse the json and just store the "leafs" in map. Note: array of primitives will turn into the last value in the array with this approach, but that's what you described :)

Something like this:

void flatJson() throws JSONException {
    JSONObject object = new JSONObject(userJsonAsString); // this is your input
    Map<String, Object> flatKeyValue = new HashMap<>();
    readValues(object, flatKeyValue);
    System.out.println(new JSONObject(flatKeyValue)); // this is flat
}

void readValues(JSONObject object, Map<String, Object> json) throws JSONException {
    for (Iterator it = object.keys(); it.hasNext(); ) {
        String key = (String) it.next();
        Object next = object.get(key);
        readValue(json, key, next);
    }
}

void readValue(Map<String, Object> json, String key, Object next) throws JSONException {
    if (next instanceof JSONArray) {
        JSONArray array = (JSONArray) next;
        for (int i = 0; i < array.length(); ++i) {
            readValue(json, key, array.opt(i));
        }
    } else if (next instanceof JSONObject) {
        readValues((JSONObject) next, json);
    } else {
        json.put(key, next);
    }
}

Upvotes: 1

Related Questions