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

时间:2015-12-18 12:42:16

标签: json retrofit

我对服务器的响应是不同类型的JSON对象的列表,这取决于每个响应的“类型”。我为每种响应类型都有不同的bean。可以使用Retrofit为列表中的每个响应(JSON对象)使用适当的Bean类吗(JSON数组)?

   {
    "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类,包含所有可能的字段,每个JSON对象几乎有一半的字段为空。
有没有更好的方法呢?

1 个答案:

答案 0 :(得分:1)

您可以创建一个超类,其中包含所有类型的通用数据并对其进行扩展:

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

希望示例中的命名不是太糟糕,你会得到这个想法:)