假设我们有这样的结构:
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
Cat
truck
{ "body": { "trucks": [ { "truck": { "id": 1, "engine": "big", "wheels": 12 } }, { "truck": { "id": 2, "engine": "super big", "wheels": 128 } } ] } }
我在上使用GSON(默认Retrofitjson解析器)Android,在提供解决方案时请考虑一下。
Retrofit
Android
我们可以在此处使用泛型,因此响应如下所示:
private final Body<ListResponse<ItemWrapper<T>> 但是我们不能,因为字段名称是特定于类的。
private final Body<ListResponse<ItemWrapper<T>>
题:
我如何做才能自动序列化它而不创建太多样板类?我并不真的需要单独的类一样BodyCat,BodyTruck,BodyAnyOtherClassInThisStructure和我正在寻找一种方法来避免它们。
BodyCat
BodyTruck
BodyAnyOtherClassInThisStructure
@编辑:
由于继承混乱,我更改了类(cat,dog-> cat,truck),此处用作示例的类不要互相扩展
一种想法是定义一个自定义的通用解串器。它的通用类型将表示包装在Body实例中的列表元素的具体类。
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]有了猫。
[1_big_12, 2_super big_128]
[1_cat1, 2_cat2]