Java Android:当键可以是JSON对象或JSON数组时解析JSON响应
我正在从我们后端团队提供的API获取数据。其中一个键数据有时包含JSONObject,有时包含JSONArray。我正在使用GSON解析响应,因此它引发了一个异常 我尝试了这个线程中给出的解决方案,但在我的情况下不起作用。 POJO EntityDetailResponseV2:Java Android:当键可以是JSON对象或JSON数组时解析JSON响应,java,android,json,gson,Java,Android,Json,Gson,我正在从我们后端团队提供的API获取数据。其中一个键数据有时包含JSONObject,有时包含JSONArray。我正在使用GSON解析响应,因此它引发了一个异常 我尝试了这个线程中给出的解决方案,但在我的情况下不起作用。 POJO EntityDetailResponseV2: 您需要使用自定义JsonDeserializer。以下是解决方案: public class CollectionListItem { @SerializedName ("type") String
您需要使用自定义JsonDeserializer。以下是解决方案:
public class CollectionListItem {
@SerializedName ("type")
String type;
@SerializedName ("order")
Integer order;
@SerializedName ("id")
Integer id;
@SerializedName ("type_id")
Integer typeId;
DataType1 dataType1;
List<DataType2> dataType2;
List<DataType3> dataType3;
final static String DATA_TYPE_1 = "SHOP";
final static String DATA_TYPE_2 = "TOP_AUDIOS";
final static String DATA_TYPE_3 = "MEDIA_COLLECTION";
//Public getters and setters
public static class CollectionItemDeserializer implements JsonDeserializer<CollectionListItem> {
@Override
public CollectionListItem deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
CollectionListItem collectionItem = new Gson().fromJson(json, CollectionListItem.class);
JsonObject jsonObject = json.getAsJsonObject();
if (collectionItem.getType() != null) {
JsonElement element = jsonObject.get("data");
switch(collectionItem.getType()){
case CollectionListItem.DATA_TYPE_1 :
collectionItem.dataType1 = new Gson().fromJson(element, DataType1.class);
break;
case CollectionListItem.DATA_TYPE_2:
List<DataType2> values = new Gson().fromJson(element, new TypeToken<ArrayList<DataType2>>() {}.getType());
collectionItem.dataType2 = values;
break;
case CollectionListItem.DATA_TYPE_3:
List<DataType3> values_ = new Gson().fromJson(element, new TypeToken<ArrayList<DataType3>>() {}.getType());
collectionItem.dataType3 = values_;
break;
}
}
return collectionItem;
}
}
}
我试过你的解决办法。我不再得到异常,但DataType1和DataType2都是空值。实际上,我只需要两个数据类型,因为数据可以是JSON对象或JSON数组,并且我可以在交换机中使用collectionItem.getTypeID而不是collectionItem.getType来区分它。我在DataType1和DataType2中都添加了view\u all boolean,但这两个都映射为null,即使类型为:SHOP的集合中的第一个响应在数据键内部有view\u all:false。我添加了有问题的新代码描述根据您提供的JSON,数据键引用了两种以上不同的数据类型。假设第一个类型是Pojo1,然后是List和List,所以您需要相应地编写条件。不要只考虑JsonObject和JsonArray,还要考虑类型1、类型2、类型3的JsonObject和JsonArray。是的,我认为像您提到的那样,为不同类型提供单独的POJO会很好。但是,为什么DataType1和DataType2都是空值呢。类型为:SHOP的集合中的第一个响应在数据键内具有view\u all:false。我已将新代码添加到问题描述中。您需要使用布尔值而不是布尔值!另外,最好不要像现在这样使用内部静态类。它们不适用于这样的用例。请阅读以下内容:
public class ArrayAdapterFactory implements TypeAdapterFactory {
@SuppressWarnings({"unchecked"})
@Override
public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> type) {
ArrayAdapter typeAdapter = null;
try {
if (type.getRawType() == List.class) {
typeAdapter = new ArrayAdapter(
(Class) ((ParameterizedType) type.getType())
.getActualTypeArguments()[0]);
}
} catch (Exception e) {
e.printStackTrace();
}
return typeAdapter;
}
public class ArrayAdapter<T> extends TypeAdapter<List<T>> {
private Class<T> adapterClass;
public ArrayAdapter(Class<T> adapterClass) {
this.adapterClass = adapterClass;
}
public List<T> read(JsonReader reader) throws IOException {
List<T> list = new ArrayList<T>();
Gson gson = new Gson();
if (reader.peek() == JsonToken.BEGIN_OBJECT) {
T inning = (T) gson.fromJson(reader, adapterClass);
list.add(inning);
} else if (reader.peek() == JsonToken.BEGIN_ARRAY) {
reader.beginArray();
while (reader.hasNext()) {
//read(reader);
T inning = (T) gson.fromJson(reader, adapterClass);
list.add(inning);
}
reader.endArray();
} else {
reader.skipValue();
}
return list;
}
public void write(JsonWriter writer, List<T> value) throws IOException {
}
}
}
public class EntityDetailResponseV2 {
@SerializedName("results")
private Results results;
@SerializedName("success")
private boolean success;
public static EntityDetailResponseV2 getObject(String res) {
try {
Gson gson = new GsonBuilder().registerTypeAdapter(Collections.class, new Results.Collections.CollectionItemDeserializer()).create();
return gson.fromJson(res, EntityDetailResponseV2.class);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public Results getResults() {
return results;
}
public boolean isSuccess() {
return success;
}
public static class Results {
@SerializedName("id")
Integer entityID;
@SerializedName("name")
String entityName;
@SerializedName("description")
String entityDescription;
@SerializedName("image_url")
String entityImageURL;
@SerializedName("square_entity_url")
String entitySquareURL;
@SerializedName("slug")
String entitySlug;
@SerializedName("live")
boolean isEntityLive;
@SerializedName("twitter_username")
String twitterUserName;
@SerializedName("fb_username")
String fbUserName;
@SerializedName("featured")
private List<EntityFeaturedResponse> featured;
@SerializedName("collections")
List<Collections> collectionsList;
public Integer getEntityID() {
return entityID;
}
public String getEntityName() {
return entityName;
}
public String getEntityDescription() {
return entityDescription;
}
public String getEntityImageURL() {
return entityImageURL;
}
public String getEntitySquareURL() {
return entitySquareURL;
}
public String getEntitySlug() {
return entitySlug;
}
public boolean isEntityLive() {
return isEntityLive;
}
public String getTwitterUserName() {
return twitterUserName;
}
public String getFbUserName() {
return fbUserName;
}
public List<EntityFeaturedResponse> getFeatured() {
return featured;
}
public List<Collections> getCollectionsList() {
return collectionsList;
}
public static class Collections {
@SerializedName("type")
String type;
@SerializedName("order")
Integer order;
@SerializedName("type_id")
Integer typeId;
DataType1 dataType1;
List<DataType2> dataType2;
public String getType() {
return type;
}
public Integer getOrder() {
return order;
}
public Integer getTypeId() {
return typeId;
}
public DataType1 getDataType1() {
return dataType1;
}
public List<DataType2> getDataType2() {
return dataType2;
}
public static class CollectionItemDeserializer implements JsonDeserializer<Collections> {
@Override
public Collections deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
Collections collectionItem = new Gson().fromJson(json, Collections.class);
JsonObject jsonObject = json.getAsJsonObject();
if (collectionItem.getType() != null) {
JsonElement element = jsonObject.get("data");
switch (collectionItem.getTypeId()) {
case AppConstants.ENTITY_SHOP:
case AppConstants.ENTITY_MEDIA_COLLECTION:
case AppConstants.ENTITY_ECOM_COLLECTION:
case AppConstants.ENTITY_BANNER:
collectionItem.dataType1 = new Gson().fromJson(element, DataType1.class);
break;
case AppConstants.ENTITY_TOP_AUDIOS:
case AppConstants.ENTITY_TOP_VIDEOS:
case AppConstants.ENTITY_LATEST_VIDEOS:
case AppConstants.ENTITY_TOP_PLAYLISTS:
case AppConstants.ENTITY_WALLPAPERS:
case AppConstants.ENTITY_QUOTATIONS:
List<DataType2> values = new Gson().fromJson(element, new TypeToken<ArrayList<DataType2>>() {}.getType());
collectionItem.dataType2 = values;
break;
}
}
return collectionItem;
}
}
public static class DataType1 {
@SerializedName("view_all")
boolean viewAll;
public boolean isViewAll() {
return viewAll;
}
}
public static class DataType2 {
@SerializedName("view_all")
boolean viewAll;
public boolean isViewAll() {
return viewAll;
}
}
}
}
}
public class CollectionListItem {
@SerializedName ("type")
String type;
@SerializedName ("order")
Integer order;
@SerializedName ("id")
Integer id;
@SerializedName ("type_id")
Integer typeId;
DataType1 dataType1;
List<DataType2> dataType2;
List<DataType3> dataType3;
final static String DATA_TYPE_1 = "SHOP";
final static String DATA_TYPE_2 = "TOP_AUDIOS";
final static String DATA_TYPE_3 = "MEDIA_COLLECTION";
//Public getters and setters
public static class CollectionItemDeserializer implements JsonDeserializer<CollectionListItem> {
@Override
public CollectionListItem deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
CollectionListItem collectionItem = new Gson().fromJson(json, CollectionListItem.class);
JsonObject jsonObject = json.getAsJsonObject();
if (collectionItem.getType() != null) {
JsonElement element = jsonObject.get("data");
switch(collectionItem.getType()){
case CollectionListItem.DATA_TYPE_1 :
collectionItem.dataType1 = new Gson().fromJson(element, DataType1.class);
break;
case CollectionListItem.DATA_TYPE_2:
List<DataType2> values = new Gson().fromJson(element, new TypeToken<ArrayList<DataType2>>() {}.getType());
collectionItem.dataType2 = values;
break;
case CollectionListItem.DATA_TYPE_3:
List<DataType3> values_ = new Gson().fromJson(element, new TypeToken<ArrayList<DataType3>>() {}.getType());
collectionItem.dataType3 = values_;
break;
}
}
return collectionItem;
}
}
}
Gson gson = new GsonBuilder()
.registerTypeAdapter(CollectionListItem.class,
new CollectionListItem.CollectionItemDeserializer())
.create();