使用Gson将json转换为Map.Entry对象 [英] Convert json to Map.Entry object with Gson
问题描述
简单版本
如果我要求Gson将一些有效的json转换为MyMap,那么这样做没有问题
public class MyMap {
Map< Long,String>内容;
$ b MyMap myMap = gson.fromJson(json,new TypeToken< MyMap>(){} .getType());
HARD VERSION:
我如何让Gson执行以下操作?
public class MyDS {
Map< Map.Entry< Long,String> ;,,地图<长,字符串>>内容;
}
MyDS myDS = gson.fromJson(json,new TypeToken< MyDS>(){} .getType());
示例json,如果您确实需要它。
< pre $
content:{
[1,dog]:{
1:max,
2: pi,
3:机器人,
4:捕手,
5:收割者
},
2,猫]:{
6:black,
7:white,
8:meow,
9 :老鼠,
10:老鼠
},
[3,rabbit]:{
16:bunny,
17:耳朵,
28:burgerbun,
39:alice,
50:tweak
}
更多笔记 $ b
为了更好的衡量,我尝试运行一个单元测试,其中我所做的只是尝试使用Gson读取json,并获得以下错误跟踪:
at sun.misc.Unsafe.allocateInstance(本地方法)
java.lang.reflect.Method.invoke!(本地方法)
com.googl e.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] for
{3,rabbit}
假设您有一个有效的 JSON
类型内容:
{
content:{
[1 ,dog):{
1:max,
2:pi,
3:robot,
4: 捕手,
5:收割者
},
[2,猫]:{
6:黑色,
7:白色,
8:喵,
9:老鼠,
10:鼠
},
[3,rabbit]:{
16:bunny,
17:耳朵,
28:burgerbun,
39:alice,
50:tweak
}
}
}
为了实现你想要的,你可以简单地实现你自己的 Map.Entry
Deserializer
,因为它不能被反序列化,因为它不是一个数组,并且 {3,rabbit}
不是有效的 > JSON
object。
因此,您的 Deserializer
可以依赖常规表达来提取关键字和值,然后使用提取的值创建一个 AbstractMap.SimpleEntry
的实例,如下所示:
public class MapEntryDeserializer实现了JsonDeserializer< Map.Entry< Long,String>> {
$ b / **
*相应的模式:
*以[
*<一个非空的数字字符序列> ;,
* <任何字符的非空序列
*结束于]
* /
private static final Pattern PATTERN = Pattern.compile(^ \\ [(\\d + ),?(。+)\\ $);
public Map.Entry< Long,String> deserialize(JsonElement json,Type typeOfT,
JsonDeserializationContext上下文)抛出JsonParseException {
//从[3,rabbit]类型的字符串中提取键/值对
String value = json.getAsString( );
匹配匹配器= PATTERN.matcher(value);
if(!matcher.find()){
throw new JsonParseException(
String.format(地图条目没有预期的格式:%s,value)
);
}
返回新的AbstractMap.SimpleEntry<>(
Long.valueOf(matcher.group(1)),matcher.group(2)
);
$ / code $ / pre
然后我可以反序列化我的
$ b 类型type = new TypeToken< MyDS>(){} .getType( );
Gson gson = new GsonBuilder()
.registerTypeAdapter(Map.Entry.class,new MapEntryDeserializer())
.create();
MyDS myDS = gson.fromJson(json,type);
EASY VERSION
If I ask Gson to convert some valid json to MyMap it has no problem doing it
public class MyMap{
Map<Long,String> content;
}
MyMap myMap = gson.fromJson(json, new TypeToken<MyMap>() {}.getType());
HARD VERSION:
How do I get Gson to do the following?
public class MyDS{
Map<Map.Entry<Long,String>,Map<Long,String>> content;
}
MyDS myDS = gson.fromJson(json, new TypeToken<MyDS>() {}.getType());
Example json if you really need it.
"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"
}
}
more notes
For good measure, I try to run a unit test where all I do is try to read the json with Gson, and I get the following error trace:
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)
It does not matter if the keys are of the form "[3, rabbit]"
for "{3, rabbit}"
解决方案 Assuming that you have a valid JSON
content of type:
{
"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"
}
}
}
To achieve what you want, you could simply implement your own Map.Entry
Deserializer
since it cannot be deserialized out of the box because it is not an array and {3, rabbit}
is not a valid JSON
object.
So your Deserializer
could rely on a regular expression to extract the key and the value then create an instance of AbstractMap.SimpleEntry
using the extracted values, something like:
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)
);
}
}
I can then deserialize my JSON
content with:
Type type = new TypeToken<MyDS>() {}.getType();
Gson gson = new GsonBuilder()
.registerTypeAdapter(Map.Entry.class, new MapEntryDeserializer())
.create();
MyDS myDS = gson.fromJson(json, type);
这篇关于使用Gson将json转换为Map.Entry对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!