假设我们有这样的结构:
JSON:
{
"body": {
"cats": [
{
"cat": {
"id": 1,
"title": "cat1"
}
},
{
"cat": {
"id": 2,
"title": "cat2"
}
}
]
}
}
和对应的POJO:
响应类
private final Body body;
身体类
private final Collection<CatWrapper> cats
CatWrapper.class
private final Cat cat
类别
private final int id;
private final String title;
但是现在让我们说,我们具有相同的结构,但是Cat
我们得到的不是truck
{
"body": {
"trucks": [
{
"truck": {
"id": 1,
"engine": "big",
"wheels": 12
}
},
{
"truck": {
"id": 2,
"engine": "super big",
"wheels": 128
}
}
]
}
}
我在上使用GSON(默认Retrofit
json解析器)Android
,在提供解决方案时请考虑一下。
我们可以在此处使用泛型,因此响应如下所示:
private final Body<ListResponse<ItemWrapper<T>>
但是我们不能,因为字段名称是特定于类的。
题:
我如何做才能自动序列化它而不创建太多样板类?我并不真的需要单独的类一样BodyCat
,BodyTruck
,BodyAnyOtherClassInThisStructure
和我正在寻找一种方法来避免它们。
@编辑:
由于继承混乱,我更改了类(cat,dog-> cat,truck),此处用作示例的类不要互相扩展
一种想法是定义一个自定义的通用解串器。它的通用类型将表示包装在Body
实例中的列表元素的具体类。
假设以下类别:
class Body<T> {
private List<T> list;
public Body(List<T> list) {
this.list = list;
}
}
class Cat {
private int id;
private String title;
...
}
class Truck {
private int id;
private String engine;
private int wheels;
...
}
从您拥有包含名为“ body”的对象的意义上说,反序列化器假定json的结构始终相同。还假定此主体的第一个键值对中的值是一个列表。
现在,对于json数组中的每个元素,我们再次需要获取与每个键关联的内部对象。我们反序列化此值并将其放在列表中。
class CustomJsonDeserializer<T> implements JsonDeserializer<Body<T>> {
private final Class<T> clazz;
public CustomJsonDeserializer(Class<T> clazz) {
this.clazz = clazz;
}
@Override
public Body<T> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonObject body = json.getAsJsonObject().getAsJsonObject("body");
JsonArray arr = body.entrySet().iterator().next().getValue().getAsJsonArray();
List<T> list = new ArrayList<>();
for(JsonElement element : arr) {
JsonElement innerElement = element.getAsJsonObject().entrySet().iterator().next().getValue();
list.add(context.deserialize(innerElement, clazz));
}
return new Body<>(list);
}
}
对于最后一步,您只需要创建相应的类型,实例化并在解析器中注册适配器即可。例如卡车:
Type truckType = new TypeToken<Body<Truck>>(){}.getType();
Gson gson = new GsonBuilder()
.registerTypeAdapter(truckType, new CustomJsonDeserializer<>(Truck.class))
.create();
Body<Truck> body = gson.fromJson(new FileReader("file.json"), truckType);
如果要摆脱Body
类,甚至可以直接从适配器返回列表。
有了卡车,您就会得到[1_big_12, 2_super big_128]
产出,而[1_cat1, 2_cat2]
有了猫。
问题内容: 我在Android应用程序(带有Gson库)中实现Json反序列化存在一些问题 我已经上了这样的课 反序列化的调用是: 问题是调用后的result.posts列表包含一个LinkedTreeMap对象数组(具有正确的值,因此问题是反序列化)而不是MyJson对象。当我使用MyObject而不是T时,一切运行正常并且MyObject是正确的。 那么,有什么方法可以在不创建自定义反序列化器
问题内容: 我想通过Google Gson传输列表对象,但是我不知道如何反序列化泛型类型。 看了这个之后我尝试了什么(BalusC的答案): 但是后来我在日食中遇到了一个错误,说“新的List(){}类型必须实现继承的抽象方法…”,如果我使用快速修复方法,则会得到20个以上的方法存根的怪兽。 我很确定有一个更简单的解决方案,但是我似乎找不到它! 编辑: 我现在有 但是,在“ fromJson”行中
我正在努力用本地化反序列化世界天气在线API结果。 是否有更好、更简单的解决方案,只为lang对象编写一个自定义反序列化器,并允许GSON自动反序列化其余数据?
问题内容: 我想编写一个通用函数,使用Gson反序列化通用类型List,下面是代码: 但是这段代码不起作用,我得到一个奇怪的结构,但是没有我的类型列表 当我使用时: 我工作,我得到了! 但是我需要一个通用函数,我该如何解决? 问候rubiktubik 问题答案: 没有将(as )的实际类型传递给您的方法,就无法做到这一点。 但是,如果显式传递它,则可以按如下所示创建for : 也可以看看:
我在Android应用程序中实现Json反序列化时遇到了一些问题(带有Gson库)
这是保存过程开始的地方。我定义了一个抽象方法,以后在运行时已知的类中实现。 这里我知道的类型,我想调用一个方法。 所以问题是ConfigurationPersistenceHelper中的方法。运行此方法时,配置中得到的不是而是。 我知道我可以在每个具体应用程序类的方法中实现反序列化器逻辑。但这会导致大量重复代码。这是我目前的解决方案。 此外,我知道我可以将类型从(其中类型在运行时仍然可用)传递给