使用 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;
}
}
希望示例中的命名不会太糟糕,您会明白的:)
我的服务器响应是一个包含不同类型 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;
}
}
希望示例中的命名不会太糟糕,您会明白的:)