1

I have a JSON file which I need to flat and create a CSV from it. I was able to convert to CSV (I have a "users" wrapper) but inside "users" there is another wrapper named "identifiers", I want to iterate them as well and create a field for them.

I have a JSON file which looks like this :

{
  "users": [
    {
      "displayName": "Sharad Dutta",
      "givenName": "",
      "surname": "",
      "extension_user_type": "user",
      "identities": [
        {
          "signInType": "emailAddress",
          "issuerAssignedId": "kkr007@gmail.com"
        }
      ],
      "extension_timezone": "VET",
      "extension_locale": "en-GB",
      "extension_tenant": "EG12345"
    },
    {
      "displayName": "Wayne Rooney",
      "givenName": "Wayne",
      "surname": "Rooney",
      "extension_user_type": "user",
      "identities": [
        {
          "signInType": "userName",
          "issuerAssignedId": "kkr007"
        }
      ],
      "extension_timezone": "VET",
      "extension_locale": "en-GB",
      "extension_tenant": "EG12345"
    }
  ]
}

I am trying to convert the JSON to CSV and this is what I was able to do :

enter image description here

Below is the code : As you can see, my JSON is wrapped inside a "users" type wrapper and in the JSON i have one more wrapper "identities", with the code that I did, I am able to iterate but the "identites" is coming out as JSON blob, I want something like this in place of identites

issuerType       issuerAssignedId
bla bla bla      bla bla bla

and not a JSON nested blol for identites.

public static void main(String[] args) throws JSONException {

        String userJsonFile = "C:\\Users\\Administrator\\Desktop\\jsonRes\\json_format_user_data_input_file.json";

        try {
            userJsonAsString = readFileAsAString(userJsonFile);
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        JSONObject output;
        try {
            output = new JSONObject(userJsonAsString);
            JSONArray docs = output.getJSONArray("users");
           
            File file = new File("C:\\Users\\Administrator\\Desktop\\jsonRes\\EmpDetails.csv");
            String csv = CDL.toString(docs);
            
            FileUtils.writeStringToFile(file, csv);
            System.out.println("Data has been Sucessfully Writeen to " + file);
            System.out.println(csv);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    private static String readFileAsAString(String inputJsonFile) throws Exception {
        
        return new String(Files.readAllBytes(Paths.get(inputJsonFile)));
    }
horizon
  • 453
  • 2
  • 12
  • First flatten your JSON - then write the flattened structure to your CSV: [How to deserialize JSON into flat, Map-like structure?](https://stackoverflow.com/questions/20355261/how-to-deserialize-json-into-flat-map-like-structure) There are more [answers and approaches here](https://stackoverflow.com/search?tab=votes&q=%5bjava%5d%20flatten%20json), also. – andrewJames Sep 16 '20 at 13:20
  • A lot of them have used third party library. I was in search for something that I can use from java library. – SharadxDutta Sep 18 '20 at 05:24

1 Answers1

1

Welcome to SO! As you rightly said, "identities" is a nested JSON Array inside each element of the "users" array. So, when you flatten into a more-or-less relational format (here CSV), you would typically need to repeat the rest of the info for each element of the "identitites" array.

Now, whichever JSON parsing library you are using (JSONObject in you snippet, I am assuming comes from org.json jar?), you would need to iterate through the JSONArray docs and for each element call the getJSONArray("identities").

Since it is a nested array, you would need two loops to handle this scenario.

outer loop for the "users" array and a nested loop for the "identities" on each element of the "users" array.

Please use the below snippet as a reference only. Have written according to your code snippet. Please use standard variable naming and practices. This is just to show you the logic

String userJsonAsString="";
    StringBuilder sBuild = new StringBuilder();
    StringBuilder sBuild2 = new StringBuilder();
    try {
        userJsonAsString  = readFileAsAString(userJsonFile);
    } catch (Exception e1) {
        e1.printStackTrace();
    }
    JSONObject output;
    try {
        output = new JSONObject(userJsonAsString);
        JSONArray docs = output.getJSONArray("users");
        
        Iterator<Object> iter =   docs.iterator();
        
        while(iter.hasNext()) {
            JSONObject userEleObj = (JSONObject)iter.next();
             JSONArray nestedIdArray = userEleObj.getJSONArray("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(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();
    }
Ed Bighands
  • 159
  • 8
  • I am not able to figure out, can you suggest for a start? – horizon Sep 18 '20 at 11:46
  • Iterator iter = docs.iterator(); My IDE is showing this is not a valid syntax? Am i missing something here? – horizon Sep 21 '20 at 04:30
  • The method iterator() is undefined for the type JSONArray --> I am getting this. I think it is because I am using JSONArray which is external lib. – horizon Sep 21 '20 at 05:49
  • In that case, whatever is the ext lib jar you are using, you can replace the iterators with simple for loops and achieve the same – Ed Bighands Sep 21 '20 at 06:06
  • Yes I did that, now working on the rest of the code, can you please help me with the lambda expression? can you please change it to a non-lambda expression? Thanks in advance! – horizon Sep 21 '20 at 06:12
  • Hi Ed, sorry to bother you so much! Please check the question part, I have updated the what error I am facing and what is I tried in place of iterator (i used for loop). – horizon Sep 21 '20 at 06:35
  • 1
    You will be able to use my snippet as is with Java8+ and org.json jar as a library in your classpath – Ed Bighands Sep 21 '20 at 06:57
  • It worked, I am getting a comma separated like this -> VET,EG12345,en-GB,userName,tytytytyty,Wayne Rooney,Rooney,Wayne,user – horizon Sep 21 '20 at 07:52
  • BUT, I am not getting column_name, I got row_values, should I append it manually? – horizon Sep 21 '20 at 07:53
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/221806/discussion-between-ed-bighands-and-horizon). – Ed Bighands Sep 21 '20 at 09:33