本文介绍了Android:当键可以是JSON对象或JSON数组时,解析JSON响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am fetching data from API provided by our Backend team. One of the keys data sometimes contains JSONObject and sometimes it contains JSONArray. I am using GSON to parse the response and it is throwing an exception because of this.

我尝试了此线程中给出的解决方案,但在我的情况下不起作用.如何动态处理json响应数组/使用Gson的对象

I tried the solution given in this thread but it's not working in my case.How to dynamically handle json response array/object using Gson

POJO(EntityDetailResponseV2):

package com.tf.eros.faythTv.objects.entityDetail;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.annotations.SerializedName;
import com.tf.eros.faythTv.objects.entityFeatured.EntityFeaturedResponse;
import com.tf.eros.faythTv.utils.ArrayAdapterFactory;

import java.util.List;

public class EntityDetailResponseV2 {

    @SerializedName("results")
    private Results results;

    @SerializedName("success")
    private boolean success;

    public static EntityDetailResponseV2 getObject(String res) {

        try {
            Gson gson = new GsonBuilder().registerTypeAdapterFactory(new ArrayAdapterFactory()).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("type_id")
            Integer typeID;

            //Data sometimes contains JSON object and sometimes it contains JSON Array
            @SerializedName("data")
            List<Data> data;

            public String getType() {
                return type;
            }

            public Integer getTypeID() {
                return typeID;
            }

            public List<Data> getData() {
                return data;
            }

            public static class Data {

                @SerializedName("view_all")
                boolean viewAll;

                @SerializedName("title")
                String title;

                public boolean isViewAll() {
                    return viewAll;
                }

                public String getTitle() {
                    return title;
                }
            }
        }
    }

}

ArrayAdapterFactory.java

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 {

        }

    }
}

由于完整的API响应非常大,因此我提供了指向.json文件的链接. https://drive.google.com/open?id=1RMOiM7UjOwR-5b0Ik7ymy65ZOhc8I8hY

As complete API response is very large, I am providing a link to .json file. https://drive.google.com/open?id=1RMOiM7UjOwR-5b0Ik7ymy65ZOhc8I8hY

更新:我尝试了下面提到的解决方案,但DataType1和DataType2都为空.尽管我不再遇到GSON例外.

UPDATE:I tried the solution which is mentioned below but still, DataType1 and DataType2 both are coming nulls. Although I am no longer getting the GSON exception.

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

    }

}

推荐答案

您需要使用自定义JsonDeserializer.解决方法如下:

You need to use a custom JsonDeserializer. Here's the solution :

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等是用于不同响应的各个类.

DataType1, DataType2, etc are the individual classes for different responses.

此外,添加此行以向gson注册您的自定义解串器

Also, add this line to register your custom deserializer with gson

Gson gson = new GsonBuilder()
            .registerTypeAdapter(CollectionListItem.class,
                    new CollectionListItem.CollectionItemDeserializer())
            .create();

这篇关于Android:当键可以是JSON对象或JSON数组时,解析JSON响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-20 20:45