gpt4 book ai didi

java - Gson 序列化多态对象列表

转载 作者:IT老高 更新时间:2023-10-28 12:46:34 24 4
gpt4 key购买 nike

我正在尝试使用 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:BatchInobixBatchout 字符串丢失)。这是我的基类:

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;
}
}

我意识到我可以为此使用适配器,但问题是我正在序列化基类类型 ObixBaseObj 的集合。大约有 25 个类继承自此。我怎样才能优雅地完成这项工作?

最佳答案

有一个简单的解决方案:Gson's RuntimeTypeAdapterFactory (来自 com.google.code.gson:gson-extras:$gsonVersion)。您不必编写任何序列化程序,这个类为您工作。用你的代码试试这个:

    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);

RuntimeTypeAdapterFactory<ObixBaseObj> adapter =
RuntimeTypeAdapterFactory
.of(ObixBaseObj.class)
.registerSubtype(ObixBaseObj.class)
.registerSubtype(ObixOp.class);


Gson gson2=new GsonBuilder().setPrettyPrinting().registerTypeAdapterFactory(adapter).create();
Gson gson = new Gson();
System.out.println(gson.toJson(lobbyObj));
System.out.println("---------------------");
System.out.println(gson2.toJson(lobbyObj));

}

输出:

{"obix":"obj","is":"obix:Lobby","children":[{"obix":"op","name":"batch","children":[]}]}
---------------------
{
"type": "ObixBaseObj",
"obix": "obj",
"is": "obix:Lobby",
"children": [
{
"type": "ObixOp",
"in": "obix:BatchIn",
"out": "obix:BatchOut",
"obix": "op",
"name": "batch",
"children": []
}
]
}

编辑:更好的工作示例。

您说大约有 25 个类继承自 ObixBaseObj

我们开始编写一个新类,GsonUtils

public class GsonUtils {

private static final GsonBuilder gsonBuilder = new GsonBuilder()
.setPrettyPrinting();

public static void registerType(
RuntimeTypeAdapterFactory<?> adapter) {
gsonBuilder.registerTypeAdapterFactory(adapter);
}

public static Gson getGson() {
return gsonBuilder.create();
}

每次我们需要一个Gson对象时,我们都会调用

,而不是调用 new Gson()
GsonUtils.getGson()

我们将此代码添加到 ObixBaseObj:

public class ObixBaseObj {
protected String obix;
private String display;
private String displayName;
private String name;
private String is;
private ArrayList<ObixBaseObj> children = new ArrayList<ObixBaseObj>();
// new code
private static final RuntimeTypeAdapterFactory<ObixBaseObj> adapter =
RuntimeTypeAdapterFactory.of(ObixBaseObj.class);

private static final HashSet<Class<?>> registeredClasses= new HashSet<Class<?>>();

static {
GsonUtils.registerType(adapter);
}

private synchronized void registerClass() {
if (!registeredClasses.contains(this.getClass())) {
registeredClasses.add(this.getClass());
adapter.registerSubtype(this.getClass());
}
}
public ObixBaseObj() {
registerClass();
obix = "obj";
}

为什么?因为每次实例化这个类或 ObixBaseObj 的子类时,它将在 RuntimeTypeAdapter

中注册的类

在子类中,只需要进行最小的更改:

public class ObixOp extends ObixBaseObj {
private String in;
private String out;

public ObixOp() {
super();
obix = "op";
}

public ObixOp(String in, String out) {
super();
obix = "op";
this.in = in;
this.out = out;
}

工作示例:

public static void main(String[] args) {

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 = GsonUtils.getGson();
System.out.println(gson.toJson(lobbyObj));

}

输出:

{
"type": "ObixBaseObj",
"obix": "obj",
"is": "obix:Lobby",
"children": [
{
"type": "ObixOp",
"in": "obix:BatchIn",
"out": "obix:BatchOut",
"obix": "op",
"name": "batch",
"children": []
}
]
}

希望对你有帮助。

关于java - Gson 序列化多态对象列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19588020/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com