google/gson · error · JsonSyntaxException
duplicate key
Error message
duplicate key: ${key} What it means
When Gson deserializes a Map from the array-of-entries JSON form (used with complex map key serialization), MapTypeAdapterFactory checks each key and throws JsonSyntaxException("duplicate key: ...") if a key already exists in the map. This enforces map integrity at deserialization time rather than silently overwriting an entry.
Solutions
- Remove duplicate keys at the data source before serialization
- Pre-process the JSON (or the JsonElement tree) to deduplicate entries before fromJson
- If duplicates are semantically acceptable, deserialize to a List of pairs and dedupe/merge in Java
Example fix
// before - JSON has duplicate keys (array form) [["k",1],["k",2]] // after - deduplicated source [["k",1]] // or merge duplicates in Java before building the map
Defensive patterns
Strategy: validation
Validate before calling
// Deduplicate keys before deserialization (array-of-entries form)
JsonArray arr = JsonParser.parseString(json).getAsJsonArray();
java.util.Set<String> seen = new java.util.HashSet<>();
JsonArray deduped = new JsonArray();
for (JsonElement e : arr) {
String k = e.getAsJsonArray().get(0).getAsString();
if (seen.add(k)) deduped.add(e);
}
Map<String,V> map = gson.fromJson(deduped, mapType); Try / catch
try {
Map<K,V> m = gson.fromJson(json, mapType);
} catch (com.google.gson.JsonSyntaxException e) {
// 'duplicate key': pre-dedupe the source and retry, or deserialize to a List and merge
} Prevention
- Validate source data for key uniqueness at ingestion
- Use a JsonObject/JsonArray pre-parse step to deduplicate before fromJson
- If duplicates are valid, deserialize to a List of pairs and merge in Java
When it happens
Trigger: Deserializing to Map<K,V> from JSON shaped like [["k",v1],["k",v2]] (array form) where the same key k appears more than once; data generated without key uniqueness guarantees.
Common situations: Malformed or duplicated source data; aggregation pipelines that emit repeated keys; switching a producer from object form to array form without deduplication.
Related errors
- Expecting number, got
- String contains non-ASCII characters
- Unexpected token
- Array must have size 1, but has size
- Attempted to deserialize a java.lang.Class. Forgot to…
AI-assisted analysis of google/gson@310ac341f2 (2026-08-10).
Data as JSON: /api/errors/33b3801823fcd9da.
Report an issue: GitHub.
Appendix: source
Thrown at gson/src/main/java/com/google/gson/internal/bind/MapTypeAdapterFactory.java:192
@Override
public Map<K, V> read(JsonReader in) throws IOException {
JsonToken peek = in.peek();
if (peek == JsonToken.NULL) {
in.nextNull();
return null;
}
Map<K, V> map = constructor.construct();
if (peek == JsonToken.BEGIN_ARRAY) {
in.beginArray();
while (in.hasNext()) {
in.beginArray(); // entry array
K key = keyTypeAdapter.read(in);
V value = valueTypeAdapter.read(in);
if (map.containsKey(key)) {
throw new JsonSyntaxException("duplicate key: " + key);
}
map.put(key, value);
in.endArray();
}
in.endArray();
} else {
in.beginObject();
while (in.hasNext()) {
JsonReaderInternalAccess.INSTANCE.promoteNameToValue(in);
K key = keyTypeAdapter.read(in);
V value = valueTypeAdapter.read(in);
if (map.containsKey(key)) {
throw new JsonSyntaxException("duplicate key: " + key);
}
map.put(key, value);
}
in.endObject();
}View on GitHub (pinned to 310ac341f2)