Convert JSON object with duplicate keys to JSON array

时光总嘲笑我的痴心妄想 提交于 2019-12-01 18:09:10

As of today the org.json library version 20170516 provides accumulate() method that stores the duplicate key entries into JSONArray

JSONObject jsonObject = new JSONObject();
jsonObject.accumulate("a", "b");
jsonObject.accumulate("c", "d");
jsonObject.accumulate("c", "e");
jsonObject.accumulate("f", "g");
System.out.println(jsonObject);

Output:
{
"a":"b",
"c":["d","e"],
"f":"g"
}

I want to remove the repeated keys by combining their values into an array.

Think other than JSON parsing library. It's very simple Java Program using String.split() method that convert Json String into Map<String, List<String>> without using any library.

Sample code:

String jsonString = ...
// remove enclosing braces and double quotes
jsonString = jsonString.substring(2, jsonString.length() - 2);

Map<String, List<String>> map = new HashMap<String, List<String>>();
for (String values : jsonString.split("\",\"")) {
    String[] keyValue = values.split("\":\"");
    String key = keyValue[0];
    String value = keyValue[1];

    if (!map.containsKey(key)) {
        map.put(key, new ArrayList<String>());
    }
    map.get(key).add(value);
}

output:

{
  "f": ["g"],
  "c": ["d","e"],
  "a": ["b"]
}

In order to accomplish what you want, you need to create some sort of custom class since JSON cannot technically have 2 values at one key. Below is an example:

public class SomeClass {

Map<String, List<Object>> values = new HashMap<String, List<Object>>();

public void add(String key, Object o) {
    List<Object> value = new ArrayList<Object>();
    if (values.containsKey(key)) {
        value = values.get(key);
    }
    value.add(o);
    values.put(key, value);
}

public JSONObject toJson() throws JSONException {
    JSONObject json = new JSONObject();
    JSONArray tempArray = null;

    for (Entry<String, List<Object>> en : values.entrySet()) {
        tempArray = new JSONArray();
        for (Object o : en.getValue()) {
            tempArray.add(o);
        }
        json.put(en.getKey(), tempArray);
    }

    return json;
}
}

You can then retrieve the values from the database, call the .add(String key, Object o) function with the column name from the database, and the value (as the Object param). Then call .toJson() when you are finished.

Thanks to Mike Elofson and Braj for helping me in the right direction. I only wanted to have the keys with multiple values become arrays so I had to modify the code a bit. Eventually I want it to work for nested JSON as well, as it currently assumes it is flat. However, the following code works for what I need it for at the moment.

public static String repeatedKeysToArrays(String jsonIn) throws JSONException 
{
    //This assumes that the json is flat
    String jsonString = jsonIn.substring(2, jsonIn.length() - 2);

    JSONObject obj = new JSONObject();
    for (String values : jsonString.split("\",\"")) {
        String[] keyValue = values.split("\":\"");
        String key = keyValue[0];
        String value = ""; 
        if (keyValue.length>1) value = keyValue[1];

        if (!obj.has(key)) {
            obj.put(key, value);
        } else {
            Object Oold = obj.get(key);
            ArrayList<String> newlist = new ArrayList<String>();

            //Try to cast as JSONArray. Otherwise, assume it is a String
            if (Oold.getClass().equals(JSONArray.class)) {
                JSONArray old = (JSONArray)Oold;
                //Build replacement value
                for (int i=0; i<old.length(); i++) {
                    newlist.add( old.getString(i) );
                }
            }
            else if (Oold.getClass().equals(String.class)) newlist = new ArrayList<String>(Arrays.asList(new String[] {(String)Oold})); 
            newlist.add(value);

            JSONArray newarr = new JSONArray( newlist );
            obj.put(key,newarr);                
        }
    }
    return obj.toString();
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!