4 java serialization json gson deserialization
我收到错误:
Exception in thread "main" com.google.gson.JsonParseException:
Expecting object found: "com.shagie.app.SimpleMap$Data@24a37368"
Run Code Online (Sandbox Code Playgroud)
尝试解除使用非平凡键的Map时:
package com.shagie.app;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.util.HashMap;
public class SimpleMap {
public static void main(String[] args) {
Wrapper w = new Wrapper();
w.m.put(new Data("f", 1), new Data("foo", 3));
w.m.put(new Data("b", 2), new Data("bar", 4));
GsonBuilder gb = new GsonBuilder();
gb.setPrettyPrinting();
Gson g = gb.create();
String json = g.toJson(w);
System.out.println(json);
w = g.fromJson(json, Wrapper.class);
System.out.println(w.m.isEmpty());
}
static public class Wrapper {
HashMap<Data, Data> m = new HashMap<Data, Data>();
}
static public class Data {
String s;
Integer i;
public Data(String arg, Integer val) { s = arg; i = val; }
}
}
Run Code Online (Sandbox Code Playgroud)
这序列化为json:
{
"m": {
"com.shagie.app.SimpleMap$Data@24a37368": {
"s": "foo",
"i": 3
},
"com.shagie.app.SimpleMap$Data@66edc3a2": {
"s": "bar",
"i": 4
}
}
}
可以看到尝试序列化的密钥,但肯定不是可以反序列化的.
如何序列化此对象以便可以反序列化?
dad*_*son 10
我在尝试解决这个难题时发现了以下内容:问题210:无法使用复杂键序列化或反序列化地图.
对于未来的任何互联网旅行者(如我自己)...您可以使用GsonBuilder上的enableComplexMapKeySerialization()方法在GSON 2.*中启用此功能.
启用后,映射将作为[key,value]数组的数组序列化(并正确反序列化):
{"m":[[{"s":"f", "i",1}, {"s":"foo", "i":3}], [{"s":"b", "i",2}, {"s":"bar", "i":4}]]}
Run Code Online (Sandbox Code Playgroud)
小智 4
问题是toString()在映射的键上调用,而不是它们本身被序列化。
要解决此问题,需要设置自定义序列化器和反序列化器,并且反序列化器需要了解对象用于将自身显示为字符串的格式(该toString()方法必须返回可用于重建整个对象的字符串) )。
对于上面的例子:
package com.shagie.app;
import com.google.gson.*;
import java.lang.reflect.Type;
import java.util.HashMap;
public class SimpleMapFixed {
public static void main(String[] args) {
Wrapper w = new Wrapper();
w.m.put(new Data("f", 1), new Data("foo", 3));
w.m.put(new Data("b", 2), new Data("bar", 4));
GsonBuilder gb = new GsonBuilder();
gb.setPrettyPrinting();
gb.registerTypeAdapter(Data.class, new DataSerializer());
Gson g = gb.create();
String json = g.toJson(w);
System.out.println(json);
w = g.fromJson(json, Wrapper.class);
System.out.println(w.m.isEmpty());
}
static public class Wrapper {
HashMap<Data, Data> m = new HashMap<Data, Data>();
}
static public class DataSerializer implements JsonSerializer<Data>,
JsonDeserializer<Data> {
@Override
public Data deserialize(JsonElement je, Type t, JsonDeserializationContext ctx)
throws JsonParseException {
Data rv;
JsonObject jo;
System.out.println("deserialize called with: " + je.toString());
if (je.isJsonObject()) {
jo = je.getAsJsonObject();
rv = new Data(jo.get("s").getAsString(), jo.get("i").getAsInt());
} else {
String js = je.getAsString();
String[] s = js.split(":", 2); // split into two (and only two)
rv = new Data(s[1], Integer.valueOf(s[0]));
}
System.out.println("deserialize returns: " + rv.s + " " + rv.i);
return rv;
}
@Override
public JsonElement serialize(Data data, Type type, JsonSerializationContext jsonSerializationContext) {
JsonObject jo = new JsonObject();
jo.addProperty("s", data.s);
jo.addProperty("i", data.i);
System.out.println("serialize called: " + jo.toString());
return jo;
}
}
static public class Data {
String s;
Integer i;
public Data(String arg, Integer val) { s = arg; i = val; }
@Override
public String toString() {
String rv = i.toString() + ':' + s;
System.out.println("toString called: " + rv);
return rv;
}
}
}
Run Code Online (Sandbox Code Playgroud)
运行此代码会产生:
序列化调用:{"s":"foo","i":3}
toString 调用:1:f
序列化调用:{"s":"bar","i":4}
toString 调用:2:b
{
“米”:{
“1:f”:{
“s”:“富”,
“我”:3
},
“2:b”:{
“s”:“酒吧”,
“我”:4
}
}
}
反序列化调用:“1:f”
反序列化返回:f 1
反序列化调用:{"s":"foo","i":3}
反序列化返回: foo 3
反序列化调用:“2:b”
反序列化返回:b 2
反序列化调用:{"s":"bar","i":4}
反序列化返回:栏 4
toString()请注意作为序列化一部分的调用。在此代码中,从 String 形式反序列化的逻辑位于 中DataSerializer,尽管将其作为另一个构造函数移动到类中可能是有意义的Data- 它不会影响最终结果。
进一步注意,这Data是一个相当简单的对象本身,没有更深层次的结构。尝试将其序列化为密钥需要额外的工作。
| 归档时间: |
|
| 查看次数: |
4115 次 |
| 最近记录: |