EASY VERSION
如果我要求Gson将一些有效的json转换为MyMap,那么它就没有问题了
public class MyMap{
Map<Long,String> content;
}
MyMap myMap = gson.fromJson(json, new TypeToken<MyMap>() {}.getType());
HARD VERSION:
如何让Gson执行以下操作?
public class MyDS{
Map<Map.Entry<Long,String>,Map<Long,String>> content;
}
MyDS myDS = gson.fromJson(json, new TypeToken<MyDS>() {}.getType());
示例json,如果你真的需要它。
"content": {
"[1, dog]": {
"1": "max",
"2": "pi",
"3": "robot",
"4": "catcher",
"5": "reaper"
},
"[2, cat]": {
"6": "black",
"7": "white",
"8": "meow",
"9": "mice",
"10": "rat"
},
"[3, rabbit]": {
"16": "bunny",
"17": "ears",
"28": "burgerbun",
"39": "alice",
"50": "tweak"
}
}
更多笔记
为了更好的衡量,我尝试运行单元测试,我所做的就是尝试用Gson读取json,并得到以下错误跟踪:
at sun.misc.Unsafe.allocateInstance(Native method)
java.lang.reflect.Method.invoke!(Native method)
com.google.gson.internal.UnsafeAllocator$1.newInstance(UnsafeAllocator.java:48)
com.google.gson.internal.ConstructorConstructor$14.construct(ConstructorConstructor.java:223)
com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:207)
com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40)
com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:186)
com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:145)
com.google.gson.Gson.fromJson(Gson.java:861)
com.google.gson.Gson.fromJson(Gson.java:826)
com.google.gson.Gson.fromJson(Gson.java:775)
如果密钥的格式为"[3, rabbit]"
"{3, rabbit}"
,则无关紧要
答案 0 :(得分:4)
假设您有有效 JSON
类型的内容:
{
"content": {
"[1, dog]": {
"1": "max",
"2": "pi",
"3": "robot",
"4": "catcher",
"5": "reaper"
},
"[2, cat]": {
"6": "black",
"7": "white",
"8": "meow",
"9": "mice",
"10": "rat"
},
"[3, rabbit]": {
"16": "bunny",
"17": "ears",
"28": "burgerbun",
"39": "alice",
"50": "tweak"
}
}
}
要实现您想要的功能,您可以简单地实现自己的Map.Entry
Deserializer
,因为它不能开箱即用,因为它不是数组且{3, rabbit}
不是有效的JSON
对象。
因此,您的Deserializer
可以依赖正则表达式来提取密钥和值,然后使用提取的值创建AbstractMap.SimpleEntry
的实例,例如:
public class MapEntryDeserializer implements JsonDeserializer<Map.Entry<Long, String>> {
/**
* Pattern corresponding to:
* Starts with [
* <a non empty sequence of digit characters>,
* <a non empty sequence of any characters
* Ends with ]
*/
private static final Pattern PATTERN = Pattern.compile("^\\[(\\d+), ?(.+)\\]$");
public Map.Entry<Long, String> deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context) throws JsonParseException {
// Extract the key/value pair from Strings of type [3, rabbit]
String value = json.getAsString();
Matcher matcher = PATTERN.matcher(value);
if (!matcher.find()) {
throw new JsonParseException(
String.format("The map entry doesn't have the expected format: %s", value)
);
}
return new AbstractMap.SimpleEntry<>(
Long.valueOf(matcher.group(1)), matcher.group(2)
);
}
}
然后我可以使用以下内容反序列化JSON
内容:
Type type = new TypeToken<MyDS>() {}.getType();
Gson gson = new GsonBuilder()
.registerTypeAdapter(Map.Entry.class, new MapEntryDeserializer())
.create();
MyDS myDS = gson.fromJson(json, type);
答案 1 :(得分:1)
根据Map.Entry的文档:
获取对映射条目的引用的唯一方法是来自迭代器 这个集合视图。
https://docs.oracle.com/javase/8/docs/api/java/util/Map.Entry.html
这意味着在创建初始Map之前,您无法获取Map.Entry。为了实现您想要的功能,您需要将JSON解析为Map,然后迭代它以将其插入MyDS对象。
话虽如此,根据您的最终用途,可能有更好的方法在解析数据后重新组织/键入数据。