我正在尝试使用Gson将涉及多态的对象序列化/反序列化为JSON。
这是我的序列化代码:
ObixBaseObj lobbyObj = new ObixBaseObj();
lobbyObj.setIs("obix:Lobby");
ObixOp batchOp = new ObixOp();
batchOp.setName("batch");
batchOp.setIn("obix:BatchIn");
batchOp.setOut("obix:BatchOut");
lobbyObj.addChild(batchOp);
Gson gson = new Gson();
System.out.println(gson.toJson(lobbyObj));
结果如下:
{"obix":"obj","is":"obix:Lobby","children":[{"obix":"op","name":"batch"}]}
序列化大多的作品,除了它缺少继承成员的内容(尤其是obix:BatchIn
和obixBatchout
字符串丢失)。这是我的基类:
public class ObixBaseObj {
protected String obix;
private String display;
private String displayName;
private ArrayList<ObixBaseObj> children;
public ObixBaseObj()
{
obix = "obj";
}
public void setName(String name) {
this.name = name;
}
...
}
这是我的继承类(ObixOp)的样子:
public class ObixOp extends ObixBaseObj {
private String in;
private String out;
public ObixOp() {
obix = "op";
}
public ObixOp(String in, String out) {
obix = "op";
this.in = in;
this.out = out;
}
public String getIn() {
return in;
}
public void setIn(String in) {
this.in = in;
}
public String getOut() {
return out;
}
public void setOut(String out) {
this.out = out;
}
}
我意识到我可以为此使用适配器,但是问题是我正在序列化基类type的集合ObixBaseObj
。从中继承大约25个类。我该如何优雅地进行这项工作?
我认为自定义序列化器/反序列化器是继续进行的唯一方法,我尝试向您建议实现我发现的最紧凑的方法。对于没有使用您的类,我深表歉意,但是想法是一样的(我只想要至少1个基类和2个扩展类)。
BaseClass.java
public class BaseClass{
@Override
public String toString() {
return "BaseClass [list=" + list + ", isA=" + isA + ", x=" + x + "]";
}
public ArrayList<BaseClass> list = new ArrayList<BaseClass>();
protected String isA="BaseClass";
public int x;
}
ExtendedClass1.java
public class ExtendedClass1 extends BaseClass{
@Override
public String toString() {
return "ExtendedClass1 [total=" + total + ", number=" + number
+ ", list=" + list + ", isA=" + isA + ", x=" + x + "]";
}
public ExtendedClass1(){
isA = "ExtendedClass1";
}
public Long total;
public Long number;
}
ExtendedClass2.java
public class ExtendedClass2 extends BaseClass{
@Override
public String toString() {
return "ExtendedClass2 [total=" + total + ", list=" + list + ", isA="
+ isA + ", x=" + x + "]";
}
public ExtendedClass2(){
isA = "ExtendedClass2";
}
public Long total;
}
CustomDeserializer.java
public class CustomDeserializer implements JsonDeserializer<List<BaseClass>> {
private static Map<String, Class> map = new TreeMap<String, Class>();
static {
map.put("BaseClass", BaseClass.class);
map.put("ExtendedClass1", ExtendedClass1.class);
map.put("ExtendedClass2", ExtendedClass2.class);
}
public List<BaseClass> deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context) throws JsonParseException {
List list = new ArrayList<BaseClass>();
JsonArray ja = json.getAsJsonArray();
for (JsonElement je : ja) {
String type = je.getAsJsonObject().get("isA").getAsString();
Class c = map.get(type);
if (c == null)
throw new RuntimeException("Unknow class: " + type);
list.add(context.deserialize(je, c));
}
return list;
}
}
CustomSerializer.java
public class CustomSerializer implements JsonSerializer<ArrayList<BaseClass>> {
private static Map<String, Class> map = new TreeMap<String, Class>();
static {
map.put("BaseClass", BaseClass.class);
map.put("ExtendedClass1", ExtendedClass1.class);
map.put("ExtendedClass2", ExtendedClass2.class);
}
@Override
public JsonElement serialize(ArrayList<BaseClass> src, Type typeOfSrc,
JsonSerializationContext context) {
if (src == null)
return null;
else {
JsonArray ja = new JsonArray();
for (BaseClass bc : src) {
Class c = map.get(bc.isA);
if (c == null)
throw new RuntimeException("Unknow class: " + bc.isA);
ja.add(context.serialize(bc, c));
}
return ja;
}
}
}
现在,这是我用来测试整个程序的代码:
public static void main(String[] args) {
BaseClass c1 = new BaseClass();
ExtendedClass1 e1 = new ExtendedClass1();
e1.total = 100L;
e1.number = 5L;
ExtendedClass2 e2 = new ExtendedClass2();
e2.total = 200L;
e2.x = 5;
BaseClass c2 = new BaseClass();
c1.list.add(e1);
c1.list.add(e2);
c1.list.add(c2);
List<BaseClass> al = new ArrayList<BaseClass>();
// this is the instance of BaseClass before serialization
System.out.println(c1);
GsonBuilder gb = new GsonBuilder();
gb.registerTypeAdapter(al.getClass(), new CustomDeserializer());
gb.registerTypeAdapter(al.getClass(), new CustomSerializer());
Gson gson = gb.create();
String json = gson.toJson(c1);
// this is the corresponding json
System.out.println(json);
BaseClass newC1 = gson.fromJson(json, BaseClass.class);
System.out.println(newC1);
}
这是我的处决:
BaseClass [list=[ExtendedClass1 [total=100, number=5, list=[], isA=ExtendedClass1, x=0], ExtendedClass2 [total=200, list=[], isA=ExtendedClass2, x=5], BaseClass [list=[], isA=BaseClass, x=0]], isA=BaseClass, x=0]
{"list":[{"total":100,"number":5,"list":[],"isA":"ExtendedClass1","x":0},{"total":200,"list":[],"isA":"ExtendedClass2","x":5},{"list":[],"isA":"BaseClass","x":0}],"isA":"BaseClass","x":0}
BaseClass [list=[ExtendedClass1 [total=100, number=5, list=[], isA=ExtendedClass1, x=0], ExtendedClass2 [total=200, list=[], isA=ExtendedClass2, x=5], BaseClass [list=[], isA=BaseClass, x=0]], isA=BaseClass, x=0]
一些解释:该技巧由串行器/解串器中的另一个Gson完成。我只使用isA
字段来发现合适的班级。为了更快,我使用地图将isA
字符串关联到相应的类。然后,我使用第二个Gson对象进行适当的序列化/反序列化。我将其声明为静态,因此您不会因多次分配Gson而减慢序列化/反序列化。
Pro 实际上,您编写的代码并不比这更多,而是让Gson完成所有工作。您只需要记住在地图中放置一个新的子类(例外使您想起了这一点)。
缺点 您有两张地图。我认为我的实现可以做些改进以避免映射重复,但是我将它们留给您(或将来的编辑器,如果有的话)。
也许您想将序列化和反序列化统一为一个唯一的对象,应该检查TypeAdapter
类或尝试使用同时实现两个接口的对象。
我正在尝试使用Gson将一个涉及多态性的对象序列化/反序列化为JSON。 这是我的序列化代码: 结果是这样的: 序列化主要工作,除了它缺少继承成员的内容(特别是和字符串丢失)。这是我的基类: 下面是我继承的类(ObixOp)的样子: 我意识到我可以使用适配器来实现这一点,但问题是我正在序列化一个基类类型的集合。大约有25个类继承自此。我怎样才能优雅地完成这项工作?
问题内容: 使用Gson 2.2.2,我正在尝试序列化POJO(行为)的数组列表。 我有一个适配器,几乎是我在网上看到的一个副本: 我这样注册: 然后,当我尝试序列化我的ArrayList时: 我出现堆栈溢出。 似乎在线上: 它开始递归循环,一次又一次地通过我的序列化器。那么,我该如何注册它以免发生这种情况?我需要序列化列表并保持多态性。 问题答案: 看起来您发现了JsonSerializer文档
主要内容:示例我们将一个Java对象序列化为一个Json文件,然后读取该Json文件以获取对象。 在这个例子中,创建一个类。 然后将对象列化后存储在文件中,该文件将具有对象的json表示形式。 示例 在中创建一个名为的Java类文件,参考以下代码 - 执行上面示例代码,得到以下结果 -
我有一个接口,其中和实现。服务器会返回这样的响应- 相应的类来建模它是 中的声明它是哪种车辆。我需要反序列化的成一个对象取决于。如果是,我需要在反序列化和期间使用反序列化。 如何使用gson实现这一点? 编辑-这篇文章的不同之处在于类类型()包含在需要反序列化的中。这里不是。如果在内,我可以为编写自定义反序列化程序,检查,并进行相应的反序列化。但是我想我需要为编写一个自定义反序列化程序,在这里我创
我想将这个对象序列化为JSON字符串 并得到如下结果: 我试着用 但不是这样,我得到了: 个性化序列化: 欢迎提出任何建议 谢谢,马里奥
这里有人知道如何使用TypeAdapterFactory基于“type”字段进行反序列化而不需要将整个json流读取到JsonElement对象树中吗?