Ashish Bhumkar
Ashish Bhumkar

Reputation: 115

Ignore duplicate keys in JSONObject

I have a String which is in JSON Format

String str = "{\"innerkey1\":\"innervalue1\",
\"innerkey2\":\"innervalue2\",\"innerkey1\":\"innervalue3\"}";

When I am trying to create a object from this string

try  {
    JSONObject obj = new JSONObject(str); 
} catch(Exception e) {
     e.printStackTrace();
}

I am getting an error

org.json.JSONException: Duplicate key "innerkey1"

Is there any way we can create the JSONObject by ignoring the last key from the string?

Upvotes: 4

Views: 12171

Answers (5)

Aristo Michael
Aristo Michael

Reputation: 2186

You can use objectMapper to skip this error

ObjectMapper mapper = new ObjectMapper();
String json = "{\"name\":\"test\", \"name\":\"new test\"}";

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

map = mapper.readValue(json, new TypeReference<Map<String, String>>(){});

Now you can easily convert to JSONObject from map

new JSONObject(map);

Upvotes: 6

L. Cornelius Dol
L. Cornelius Dol

Reputation: 64026

I have a JSON parser which allows the using code to treat duplicate keys as elements in an array. Refer to the section, "Document Builder Code".

Upvotes: 0

Kirill Simonov
Kirill Simonov

Reputation: 8481

It is not the easiest solution, but it allows you to have duplicates in your input string and choose what to do with them (rename, drop, etc). You should use Gson library and register your own TypeAdapter responsible for serialization/deserialization of objects. It would look like this:

class NoDuplicatesAdapter extends TypeAdapter<HashMap<String, String>> {
    @Override
    public void write(JsonWriter out, HashMap<String, String> value) throws IOException {
        out.beginObject();
        for (Map.Entry<String, String> e: value.entrySet()) {
            out.name(e.getKey()).value(e.getValue());
        }
        out.endObject();
    }
    @Override
    public HashMap<String, String> read(JsonReader in) throws IOException {
        final HashMap<String, String> map = new HashMap<>();
        in.beginObject();
        while (in.hasNext()) {
            String name = in.nextName();
            // putting value to the map only if this key is not present;
            // here you can actually find duplicate keys and decide what to do with them
            map.putIfAbsent(name, in.nextString());
        }
        in.endObject();
        return map;
    }
}

It was the most complex part, now we just need to read the JSON string:

String str = "{\"innerkey1\":\"innervalue1\", \"innerkey2\":\"innervalue2\",\"innerkey1\":\"innervalue3\"}";

Type mapType = new TypeToken<Map<String, String>>() {}.getType();

Map<String, String> map = new GsonBuilder()
        .registerTypeAdapter(mapType, new NoDuplicatesAdapter())
        .create()
        .fromJson(str, mapType);

The map will contain only the first "innerkey1".

Upvotes: 0

DeBukkIt
DeBukkIt

Reputation: 102

This is a problem of the JSON specification. Depending on which specification is used, one can interpret whether duplicate keys are permissible at all. In this thread, it has been widely agreed that the definition is that a key must be unique in a JSONObject.

For this reason, you should not try to parse a probably invalid JSON object, but use a valid one.

But I would have a small suggestion for a solution: However you put it into practice, you could use the (multiple occurring) key and assign all the objects stored there as an array to this (now unique) key. So you merge several identical keys and also merge the linked objects into an array. This would at least make the JSON object valid:

{
    "a" : "x",
    "a" : "y"
}
// becomes
{
    "a" : ["x", "y"]
}

Upvotes: 3

Francis Bartkowiak
Francis Bartkowiak

Reputation: 1462

Unfortunately no. While it isn't technically against JSON standards, it isn't something that can be easily worked with/you'll be hard pressed to find a library that can parse it.

See here: https://stackoverflow.com/a/21833017/8972283

I'd recommend updating how your JSON is being created if possible.

Upvotes: 0

Related Questions