gpt4 book ai didi

java - Gson 类型适配器与自定义解串器

转载 作者:太空狗 更新时间:2023-10-29 22:44:01 27 4
gpt4 key购买 nike

下面的示例显示了一个包含抽象类(成员)集合的类(俱乐部)。我对是否需要 TypeAdapter 或 JsonDeserializer 来使反序列化正常工作感到困惑。序列化在没有任何帮助的情况下工作得很好,但反序列化会抛出异常。为了说明,我构建了以下“克隆”测试。如果有人能展示一个工作示例,我将不胜感激。

头等舱

package gson.test;
import java.util.ArrayList;

import com.google.gson.Gson;

public class Club {
public static void main(String[] args) {
// Setup a Club with 2 members
Club myClub = new Club();
myClub.addMember(new Silver());
myClub.addMember(new Gold());

// Serialize to JSON
Gson gson = new Gson();
String myJsonClub = gson.toJson(myClub);
System.out.println(myJsonClub);

// De-Serialize to Club
Club myNewClub = gson.fromJson(myJsonClub, Club.class);
System.out.println(myClub.equals(myNewClub) ? "Cloned!" : "Failed");
}

private String title = "MyClub";
private ArrayList<Member> members = new ArrayList<Member>();

public boolean equals(Club that) {
if (!this.title.equals(that.title)) return false;
for (int i=0; i<this.members.size(); i++) {
if (! this.getMember(i).equals(that.getMember(i))) return false;
}
return true;
}
public void addMember(Member newMember) { members.add(newMember); }
public Member getMember(int i) { return members.get(i); }
}

现在是抽象基类成员

package gson.test;
public abstract class Member {
private int type;
private String name = "";

public int getType() { return type; }
public void setType(int type) { this.type = type; }
public boolean equals(Member that) {return this.name.equals(that.name);}
}

以及成员(member)的两个具体子类(Gold 和 Silver)

package gson.test;
public class Gold extends Member {
private String goldData = "SomeGoldData";
public Gold() {
super();
this.setType(2);
}
public boolean equals(Gold that) {
return (super.equals(that) && this.goldData.equals(that.goldData));
}
}

package gson.test;
public class Silver extends Member {
private String silverData = "SomeSilverData";
public Silver() {
super();
this.setType(1);
}
public boolean equals(Silver that) {
return (super.equals(that) && this.silverData.equals(that.silverData));
}
}

最后输出

    {"title":"MyClub","members":[{"silverData":"SomeSilverData","type":1,"name":""},{"goldData":"SomeGoldData","type":2,"name":""}]}
Exception in thread "main" java.lang.RuntimeException: Failed to invoke public gson.test.Member() with no args
at com.google.gson.internal.ConstructorConstructor$3.construct(ConstructorConstructor.java:107)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:186)
...

最佳答案

两者都可以。您选择哪一个实际上取决于潜在的性能影响,以及愿意编写多少代码。

反序列化器更昂贵。这是因为反序列化器的输入是一个 json 树,GSon 必须为与您的类匹配的元素创建一个完整的 JsonElement 子树,然后才能将其传递给您的反序列化器。如果您的模型有很多嵌套,则成本会增加。对于普通对象,它可以忽略不计。

看来你会根据type的值知道创建哪个类将包含在目标对象中的属性。您的反序列化器需要

  • 查看已通过的 JsonElement对象,读取 type属性,判断类型
  • 调用context.deserialize()使用类和传递给您的相同元素
  • 如果类型丢失或无效则抛出错误

您的类型适配器必须更复杂。类型适配器的输入是流,而不是元素/子树。您可以完全从流中加载下一个值,解析它,然后完全按照反序列化器的方式执行,这没有意义,您可以改用反序列化器。或者,您可以读取流,查看有哪些属性,将它们保存到局部变量中,直到到达 type。属性(您无法预测它的位置),然后完成阅读其余属性,并创建您的最终 Gold/Silver基于类型的对象,以及读取和保存的所有属性。

关于java - Gson 类型适配器与自定义解串器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30631004/

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