This链接似乎表明我必须做类似以下的事情来将类型化的Map序列化为JSON:
public static class NumberTypeAdapter
implements JsonSerializer<Number>, JsonDeserializer<Number>,
InstanceCreator<Number> {
public JsonElement serialize(Number src, Type typeOfSrc, JsonSerializationContext
context) {
return new JsonPrimitive(src);
}
public Number deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context)
throws JsonParseException {
JsonPrimitive jsonPrimitive = json.getAsJsonPrimitive();
if (jsonPrimitive.isNumber()) {
return jsonPrimitive.getAsNumber();
} else {
throw new IllegalStateException("Expected a number field, but was " + json);
}
}
public Number createInstance(Type type) {
return 1L;
}
}
public static void main(String[] args) {
Map<String, Number> map = new HashMap<String, Number>();
map.put("int", 123);
map.put("long", 1234567890123456789L);
map.put("double", 1234.5678D);
map.put("float", 1.2345F);
Type mapType = new TypeToken<Map<String, Number>>() {}.getType();
Gson gson = new GsonBuilder().registerTypeAdapter(Number.class, new
NumberTypeAdapter()).create();
String json = gson.toJson(map, mapType);
System.out.println(json);
Map<String, Number> deserializedMap = gson.fromJson(json, mapType);
System.out.println(deserializedMap);
}
酷而且有效,但似乎有很多开销( 一个完整的Type Adapter类? )。我已经使用了其他JSON库,比如JSONLib,它们允许您以下列方式构建地图:
JSONObject json = new JSONObject();
for(Entry<String,Integer> entry : map.entrySet()){
json.put(entry.getKey(), entry.getValue());
}
或者,如果我有一个类似于以下内容的自定义类:
JSONObject json = new JSONObject();
for(Entry<String,MyClass> entry : map.entrySet()){
JSONObject myClassJson = JSONObject.fromObject(entry.getValue());
json.put(entry.getKey(), myClassJson);
}
该过程更加手动,但需要更少的代码,并且没有为数字创建自定义类型适配器的开销,或者在大多数情况下 用于我自己的自定义类
这是使用Gson序列化地图的唯一方法,还是有人找到了一种方法,可以击败Gson在上面链接中推荐的内容。
答案 0 :(得分:114)
只有TypeToken
部分是必要的(当涉及遗传学时)。
Map<String, String> myMap = new HashMap<String, String>();
myMap.put("one", "hello");
myMap.put("two", "world");
Gson gson = new GsonBuilder().create();
String json = gson.toJson(myMap);
System.out.println(json);
Type typeOfHashMap = new TypeToken<Map<String, String>>() { }.getType();
Map<String, String> newMap = gson.fromJson(json, typeOfHashMap); // This type must match TypeToken
System.out.println(newMap.get("one"));
System.out.println(newMap.get("two"));
输出:
{"two":"world","one":"hello"}
hello
world
答案 1 :(得分:84)
Map序列化的默认Gson实现在密钥上使用toString()
:
Gson gson = new GsonBuilder()
.setPrettyPrinting().create();
Map<Point, String> original = new HashMap<>();
original.put(new Point(1, 2), "a");
original.put(new Point(3, 4), "b");
System.out.println(gson.toJson(original));
会给:
{
"java.awt.Point[x\u003d1,y\u003d2]": "a",
"java.awt.Point[x\u003d3,y\u003d4]": "b"
}
<小时/>
enableComplexMapKeySerialization
如果您希望根据默认的Gson规则序列化Map Key,可以使用enableComplexMapKeySerialization。这将返回一组键值对数组:
Gson gson = new GsonBuilder().enableComplexMapKeySerialization()
.setPrettyPrinting().create();
Map<Point, String> original = new HashMap<>();
original.put(new Point(1, 2), "a");
original.put(new Point(3, 4), "b");
System.out.println(gson.toJson(original));
将返回:
[
[
{
"x": 1,
"y": 2
},
"a"
],
[
{
"x": 3,
"y": 4
},
"b"
]
]
可以找到更多详细信息here。
答案 2 :(得分:4)
我很确定GSON默认情况下序列化/反序列化地图和多嵌套地图(即Map<String, Map<String, Object>>
)。如果您需要做一些更复杂的事情,我认为这个例子只不过是一个起点。
查看GSON源中的MapTypeAdapterFactory类:http://code.google.com/p/google-gson/source/browse/trunk/gson/src/main/java/com/google/gson/internal/bind/MapTypeAdapterFactory.java
只要键和值的类型可以序列化为JSON字符串(并且您可以为这些自定义对象创建自己的序列化器/反序列化器),就不应该有任何问题。
答案 3 :(得分:3)
在Gson 2.7.2中,它就像
一样简单Gson gson = new Gson();
String serialized = gson.toJson(map);
答案 4 :(得分:-3)
Map<String, Object> config = gson.fromJson(reader, Map.class);