Reputation: 115
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
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
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
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
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
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