Java Android:当键可以是JSON对象或JSON数组时解析JSON响应

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

我正在从我们后端团队提供的API获取数据。其中一个键数据有时包含JSONObject,有时包含JSONArray。我正在使用GSON解析响应,因此它引发了一个异常

我尝试了这个线程中给出的解决方案,但在我的情况下不起作用。

POJO EntityDetailResponseV2:


您需要使用自定义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();