在Java中展开多维JSON

huangapple go评论60阅读模式
英文:

Flattening multidimensional JSON in JAVA

问题

{
    "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": "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"
        }
    ]
}

Java code snippet:

JSONObject output;
try {
    output = new JSONObject(userJsonAsString);
    JSONArray users = output.getJSONArray("users");
    for (int i = 0; i < users.length(); i++) {
        JSONObject user = users.getJSONObject(i);
        JSONArray identities = user.getJSONArray("identities");
        for (int j = 0; j < identities.length(); j++) {
            JSONObject flatUser = new JSONObject(user, JSONObject.getNames(user));
            JSONObject identity = identities.getJSONObject(j);
            flatUser.put("signInType", identity.getString("signInType"));
            flatUser.put("issuerAssignedId", identity.getString("issuerAssignedId"));
            System.out.println(flatUser);
        }
    }
} catch (JSONException e) {
    e.printStackTrace();
}

Flat JSON result (for each user):

{
    "extension_user_type": "user",
    "extension_locale": "en-GB",
    "extension_timezone": "VET",
    "displayName": "Sharad Dutta",
    "givenName": "",
    "surname": "",
    "extension_tenant": "EG12345",
    "signInType": "emailAddress",
    "issuerAssignedId": "kkr007@gmail.com"
}
{
    "extension_user_type": "user",
    "extension_locale": "en-GB",
    "extension_timezone": "VET",
    "displayName": "Sharad Dutta",
    "givenName": "",
    "surname": "",
    "extension_tenant": "EG12345",
    "signInType": "emailAddress",
    "issuerAssignedId": "kkr007@gmail.com"
}
英文:

I have a JSON which looks like this,

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

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(&quot;users&quot;);
            System.out.println(docs);

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

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

This is what I need,

{
    &quot;extension_timezone&quot;: &quot;VET&quot;,
    &quot;extension_tenant&quot;: &quot;EG12345&quot;,
    &quot;extension_locale&quot;: &quot;en-GB&quot;,
    &quot;signInType&quot;: &quot;emailAddress&quot;,
    &quot;issuerAssignedId&quot;: &quot;pdhongade007@gmail.com&quot;,
    &quot;displayName&quot;: &quot;Sharad Dutta&quot;,
    &quot;surname&quot;: &quot;&quot;,
    &quot;givenName&quot;: &quot;&quot;,
    &quot;extension_user_type&quot;: &quot;user&quot;
  }

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

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

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)

答案1

得分: 1

你可以遍历 JSON,只需将“叶子节点”存储在映射中。
注意:采用此方法,基本类型的数组会转换为数组中的最后一个值,但这是您描述的内容 在Java中展开多维JSON

类似于以下代码:

void flatJson() throws JSONException {
    JSONObject object = new JSONObject(userJsonAsString); // 这是您的输入
    Map<String, Object> flatKeyValue = new HashMap<>();
    readValues(object, flatKeyValue);
    System.out.println(new JSONObject(flatKeyValue)); // 这是扁平化的结果
}

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);
    }
}
英文:

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 在Java中展开多维JSON

Something like this:

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

void readValues(JSONObject object, Map&lt;String, Object&gt; 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&lt;String, Object&gt; json, String key, Object next) throws JSONException {
    if (next instanceof JSONArray) {
        JSONArray array = (JSONArray) next;
        for (int i = 0; i &lt; array.length(); ++i) {
            readValue(json, key, array.opt(i));
        }
    } else if (next instanceof JSONObject) {
        readValues((JSONObject) next, json);
    } else {
        json.put(key, next);
    }
}

答案2

得分: 1

请尝试以下方法,这将为用户和标识符(类似于扁平文件)提供逗号分隔的格式,

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 = "将您的 JSON 转换为字符串并存储在变量中";
    } 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().forEach(key -> sBuild2.append(identityEleObj.get(key) + ","));
                
                userEleObj.keySet().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();
    }
}
英文:

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 = &quot;path to your JSON&quot;;
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(&quot;users&quot;);
Iterator&lt;Object&gt; iterator = docs.iterator();
while (iterator.hasNext()) {
JSONObject userEleObj = (JSONObject)iterator.next();
JSONArray nestedIdArray = (JSONArray) userEleObj.get(&quot;identities&quot;);
Iterator&lt;Object&gt; nestIter = nestedIdArray.iterator();
while (nestIter.hasNext()) {
JSONObject identityEleObj = (JSONObject)nestIter.next(); 
identityEleObj.keySet().stream().forEach(key -&gt; sBuild2.append(identityEleObj.get(key) + &quot;,&quot;));
userEleObj.keySet().stream().forEach(key -&gt; {
if (StringUtils.equals((CharSequence) key, &quot;identities&quot;)) {
sBuild.append(sBuild2.toString());
sBuild2.replace(0, sBuild2.length(), &quot;&quot;);
} else {
sBuild.append(userEleObj.get(key) + &quot;,&quot;); 
}
});
}
sBuild.replace(sBuild.lastIndexOf(&quot;,&quot;), sBuild.length(), &quot;\n&quot;);  
}
System.out.println(sBuild);
} catch (Exception e) {
e.printStackTrace();
}
}

huangapple
  • 本文由 发表于 2020年9月18日 19:09:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/63954616.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定