我在使用GSON解析包含时间戳作为键的JSON响应时遇到重复键异常。它给出了以下错误:
com.google.gson.JsonSyntaxException:重复键:1463048935 在com.google.gson.internal.bind.MapTypeAdapterFactory $ Adapter.read(MapTypeAdapterFactory.java:186) 在com.google.gson.internal.bind.MapTypeAdapterFactory $ Adapter.read(MapTypeAdapterFactory.java:141)
如何让它忽略重复的条目,然后用重复的条目中的任何一个将其解析为地图?
答案 0 :(得分:0)
Hackerman解决方案,已使用GSON v2.8.5进行了测试和工作,但后果自负!每当您将GSON更新到新版本时,请确保检查它是否仍然有效!
基本上,您可以使用以下事实:通用ObjectTypeAdapter忽略重复项,如here所示:
就像MapTypeAdapterFactory一样,检查是否重复
V replaced = map.put(key, value);
if (replaced != null) {
throw new JsonSyntaxException("duplicate key: " + key);
}
但是ObjectTypeAdapter没有
case BEGIN_OBJECT:
Map<String, Object> map = new LinkedTreeMap<String, Object>();
in.beginObject();
while (in.hasNext()) {
map.put(in.nextName(), read(in));
}
in.endObject();
return map;
您现在可以做的是像往常一样尝试使用fromJson
进行反序列化,但是捕获了“重复密钥”异常,将其反序列化为通用对象,它将忽略重复项,再次对其进行序列化,这将导致没有重复键的JSON字符串,最后使用实际上应具有的正确类型反序列化。
这是Kotlin代码示例:
fun <T> String.deserialize(gson: Gson, typeToken: TypeToken<T>): T {
val type = typeToken.type
return try {
gson.fromJson<T>(this, type)
} catch (e: JsonSyntaxException) {
if (e.message?.contains("duplicate key") == true) {
gson.toJson(deserialize(gson, object : TypeToken<Any>() {})).deserialize(gson, typeToken)
} else {
throw e
}
}
}
很明显,这需要2个反序列化和一个附加的序列化,这增加了(可能很重)开销,但是目前我看不到有其他方法可以这样做。如果here建议,如果Google决定添加一种内置选项来忽略重复项,则最好切换到该选项。