Rahul Ramamoorthy
Rahul Ramamoorthy

Reputation: 31

Java:JSON to map using GSON

I have a string like this

{"key0":"value0","key1":"value1","key0":"value3"}

I want to store it in a map and the desired result is {"key0":"value3","key1":"value1"}

Using org.json.JsonObject: I passed the string to the constructor and Duplicate key exception is thrown

Using GSON: Same exception when I tried through new Gson.fromJson(string,Type)

Using Jackson: It does work

Is there a workaround to achieve the same using JSONObject and Gson

Upvotes: 0

Views: 966

Answers (3)

pirho
pirho

Reputation: 12275

GSON uses MapTypeAdapterFactory to deserialioze map. Below is a short excerpt of its source code where a new entry is put in a map:

V replaced = map.put(key, value);
if (replaced != null) {
    throw new JsonSyntaxException("duplicate key: " + key);
}

Knowing that there is at least one way to bypass this strict behavior: create your own map that overrides the method put(..) to return always null, like:

public class DuploMap extends HashMap<String, String>{
    @Override
    public String put(String key, String value) {
        super.put(key, value);
        return null; 
    }
}

then deserailizing to it like:

gson.fromJson(JSON, DuploMap.class);

will not throw that exception.

Upvotes: 2

Martin Meeser
Martin Meeser

Reputation: 2956

You can use GSON's JsonReader if you do not mind the manual effort.

On the plus side:

  • faster (no reflection, no casts)
  • fully under your control

--

String json = "{"key0":"value0","key1":"value1","key0":"value3"}";
JsonReader jsonReader = new JsonReader(new StringReader(json));
HashMap<String,String> map = new HashMap<String, String>()
String currKey;
try {
    while(jsonReader.hasNext()){
        JsonToken nextToken = jsonReader.peek();
           if(JsonToken.NAME.equals(nextToken)){
               currKey = jsonReader.nextName();
           }
           if(JsonToken.STRING.equals(nextToken)){
               map.put(currKey, jsonReader.nextString())
           }
    }
} catch (IOException e) {
   e.printStackTrace();
}

Upvotes: 0

Zack Macomber
Zack Macomber

Reputation: 6905

Interestingly if you first cast that json to an Object and then to a Map<String,String> your desired result happens:

String json = "{\"key0\":\"value0\",\"key1\":\"value1\",\"key0\":\"value3\"}";
Gson gson = new Gson();
Object obj = gson.fromJson(json, Object.class);
try {
    Map<String,String> map = (Map<String, String>)obj;
    // Outputs...
    // key0=value3
    // key1=value1
    for (Map.Entry<String,String> entry : map.entrySet()) {
        System.out.println(entry.getKey() + "=" + entry.getValue());
    }
} catch (ClassCastException e) {
    e.printStackTrace();
}

Upvotes: 1

Related Questions