使用 Retrofit2 处理 JSON 数组中的多个 JSON 对象类型

handle multiple JSON Objects types in a JSON Array using Retrofit2

我的服务器响应是一个包含不同类型 JSON 对象的列表,这取决于每个响应的 "type"。对于每种响应类型,我都有不同的 bean。 Retrofit 能否对列表(JSON 数组)中的每个响应(JSON 对象)使用适当的 Bean class?

   {
    "cards": [2]
        0:  {
            "type": "A"
            "ID": 24
            "author_name": "ari"
            "title": "BB"
            "permalink": ""
            "created_date": "2015-12-18 17:17:00"
            "post_date": "Dec 18 2015"
            "thumbnail": ""
            "summary": "Stars"
            "thumbSmall": "100.jpg"
            "androidXL": "500.jpg"
        }-
        1:  {
            "type": "B"
            "_id": "3290"
            "read_count": 0
            "categories": [1]
                0:  "abc"      
            "title": "New"
            "isSticky": false
            "section": [0]
            "author": "zzz"
            "india": false
            "update_time": 1450415789694
            "summary": "Social"
            "scoreId": "nz"
            "isActive": true
            "image": ""
            "timestamp": 1450385165210
            "events": [1]
                0:  "nz"
            "teams": [0]
            "slug": "new"
            "isDeleted": false
            "score_str": "SL"
        }
    }

作为解决方法,我创建了一个新的 Bean class,其中包含所有可能的字段,每个 JSON 对象的几乎一半字段为空.
有更好的方法吗?

您可以创建一个包含所有类型通用数据的超级 class 并扩展它:

public abstract class SuperItem {

 public enum Type {
    @SerializedName("A")
    TYPEA(1),

    @SerializedName("B")
    TYPEB(2);

    Type(final int value) {
        this.value = value;
    }

public static Type fromInteger(int i) {
        switch (i) {
            case 1:
                return TYPEA;
            case 2:
                return TYPEB;
            default:
                Log.d("SuperItem", "No existing type for integer: " + i);
                return null;
        }
    }
}

}

@SerializedName("type") private Type type;
}

public class AItem extends SuperItem {

}
public class BItem extends SuperItem {

}

Retrofit 默认依赖 GSON 进行 JSON 反序列化。您需要为您的实现创建自定义 Gson 反序列化器并将其设置为您的 RestAdapter:

GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(SuperItem.class, new SuperItemDeserializer());
Gson gson = builder.build();
 Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create(gson))
            .build();

您的自定义反序列化器可能如下所示:

public class SuperItemDeserializer implements     JsonDeserializer<SuperItem> {

@Override
public SuperItem deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
    Gson gson = new Gson();
    SuperItem item = null;
    JsonObject rootObject = json.getAsJsonObject();
    int typeInt = rootObject.get("type").getAsInt();
    SuperItem.Type type = SuperItem.Type.fromInteger(typeInt);
    switch (type) {
        case TYPEA:
            item = gson.fromJson(json, AItem.class);
            break;
        case TYPEB:
            item = gson.fromJson(json, BItem.class);
            break;
        default:
            Log.d("TAG", "Invalid type: " + typeInt);
    }
    return item;
}
}

希望示例中的命名不会太糟糕,您会明白的:)