java obix_Gson序列化多态对象列表

本文介绍了如何使用Gson库处理Java中的多态对象列表序列化和反序列化问题。通过自定义序列化器和反序列化器,实现了根据对象的`isA`字段动态转换类类型的功能。示例代码展示了如何创建并注册这两个适配器,并进行了测试,验证了序列化和反序列化的正确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我认为自定义序列化器/解串器是唯一的方法,我试图向您提出实现它的最紧凑的方法。我为不使用你的类而道歉,但这个想法是一样的(我只想要至少1个基类和2个扩展类)。

BaseClass.java

public class BaseClass{

@Override

public String toString() {

return "BaseClass [list=" + list + ", isA=" + isA + ", x=" + x + "]";

}

public ArrayList list = new ArrayList();

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> {

private static Map map = new TreeMap();

static {

map.put("BaseClass", BaseClass.class);

map.put("ExtendedClass1", ExtendedClass1.class);

map.put("ExtendedClass2", ExtendedClass2.class);

}

public List deserialize(JsonElement json, Type typeOfT,

JsonDeserializationContext context) throws JsonParseException {

List list = new ArrayList();

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> {

private static Map map = new TreeMap();

static {

map.put("BaseClass", BaseClass.class);

map.put("ExtendedClass1", ExtendedClass1.class);

map.put("ExtendedClass2", ExtendedClass2.class);

}

@Override

public JsonElement serialize(ArrayList 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 al = new ArrayList();

// 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类或试验一个实现两个接口的对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值