Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert JSON object with duplicate keys to JSON array

I have a JSON string that I get from a database which contains repeated keys. I want to remove the repeated keys by combining their values into an array.

For example

Input

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

Output

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

The actual data is a large file that may be nested. I will not know ahead of time what or how many pairs there are.

I need to use Java for this. org.json throws an exception because of the repeated keys, gson can parse the string but each repeated key overwrites the last one. I need to keep all the data.

If possible, I'd like to do this without editing any library code

like image 782
adamF Avatar asked Jun 25 '14 19:06

adamF


People also ask

Can JSON array have duplicate keys?

We can have duplicate keys in a JSON object, and it would still be valid. The validity of duplicate keys in JSON is an exception and not a rule, so this becomes a problem when it comes to actual implementations.

Can JSON keys be arrays?

A JSON value can be an object, array, number, string, true, false, or null, and JSON structure can be nested up to any level.

Can JSON have multiple keys with same name?

There is no "error" if you use more than one key with the same name, but in JSON, the last key with the same name is the one that is going to be used. In your case, the key "name" would be better to contain an array as it's value, instead of having a number of keys "name".

Can JSON have duplicate keys Python?

python - json. loads allows duplicate keys in a dictionary, overwriting the first value - Stack Overflow.


3 Answers

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"  
}
like image 98
Kainix Avatar answered Oct 22 '22 11:10

Kainix


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"]
}
like image 35
Braj Avatar answered Oct 22 '22 12:10

Braj


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.

like image 37
Mike Elofson Avatar answered Oct 22 '22 12:10

Mike Elofson