Android Gson解析数组中多种类型

最近空闲时间在一款仿某条的app,一开始,采用的是api store中的数据源,但是这样,好多功能因为不能得到接口支持不能实现,因此只能。。。。。。通过fiddler抓 某条 的接口了。。

在抓一个接口的时候,发现接口的json格式并不是常规的json格式,如下:


    {
        //字段太多,省略非关键部分代码
        "digg_count": 6,
        "ordered_info": [{
                "data": [{
                        "link": "链接。。。",
                        "word": "海南大学"
                    },
                    {
                        "link": "链接。。。",
                        "word": "海南航空"
                    }
                ],
                "name": "labels"
            },
            {
                "data": {
                    "like_num": 1312,
                    "user_like": 0
                },
                "name": "like_and_rewards"
            },
            {
                "ad_data": "xxxx",
                "name": "ad"
            },
            {
                "data": [{
                        "aggr_type": 1,
                        "group_id": 6519344328546976260,
                        "impr_id": "260",
                        "item_id": 6519344328546976260,
                        "log_pb": {
                            "impr_id": "201802241624280100100"
                        },
                        "open_page_url": "url",
                        "title": "阿司匹林肠溶片是终身吃,还是吃一段时间就不吃了?",
                        "type_name": ""
                    },
                    {
                        "aggr_type": 1,
                        "group_id": 6523892928937460231,
                        "impr_id": "31",
                        "item_id": 6523892928937460231,
                        "log_pb": {
                            "impr_id": "20180224162428010010023222209F57"},
                        "open_page_url": "url",
                        "title": "中国战机不如土耳其?巴铁为何弃中国战机而选择土耳其战机",
                        "type_name": ""
                    }
                ],
                "name": "related_news"
            }
        ]
    }

可以发现,ordered_info是一个数组,常规的数组,里面的bean应该是一样的字段,但是ordered_info中需要四个bean,有一种比较笨的方法,是写一个实体类,把所有的字段全部包含进去,但是如果遇到数据字段特别庞大的时候,那就呵呵哒了。

仔细观察ordered_info下的四种类型的数据,会发现他们有一个共同的字段,那就是 name,那就好办了,可以通过name这个字段让程序知道应该用哪个bean去解析。

首先建立六个bean类:BaseOrderedInfoBean、OrderedInfoBean1、OrderedInfoBean2、OrderedInfoBean3、OrderedInfoBean4、AuthorInfoBean。其中OrderedInfoBeanX是ordered_info数组下的四种类型对应的bean,BaseOrderedInfoBean是其余四个bean类的子类,AuthorInfoBean是最外层json对应的bean。

public class BaseOrderedInfoBean {
//空类
}
public class OrderedInfoBean1 extends BaseOrderedInfoBean {

 
    private String name;
    private List data;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List getData() {
        return data;
    }

    public void setData(List data) {
        this.data = data;
    }

    public static class DataBean {
   
        private String link;
        private String word;

        public String getLink() {
            return link;
        }

        public void setLink(String link) {
            this.link = link;
        }

        public String getWord() {
            return word;
        }

        public void setWord(String word) {
            this.word = word;
        }
    }
public class OrderedInfoBean2 extends BaseOrderedInfoBean {
//具体省略。。
}
public class OrderedInfoBean3 extends BaseOrderedInfoBean {
//具体省略。。
}
public class OrderedInfoBean4 extends BaseOrderedInfoBean {
//具体省略。。
}

注意:AuthorInfoBean 中的数组中必须为BaseOrderedInfoBean类型,实体类字段名应该通过@SerializedName("")来规范成java标准命名格式。

public class AuthorInfoBean{
    @SerializedName("digg_count")
    private int diggCount;
    @SerializedName("ordered_info")
    private List orderedInfos;

    public int getDiggCount() {
        return diggCount;
    }

    public void setDiggCount(int diggCount) {
        this.diggCount = diggCount;
    }

    public List getOrderedInfos() {
        return orderedInfos;
    }

    public void setOrderedInfos(List orderedInfos) {
        this.orderedInfos= orderedInfos;
    }
}

下面开始最关键的反序列化,需要一个类来实现JsonDeserializer接口,在里面处理不同的类型数据即可。

public class OrderedInfoDeserializer implements JsonDeserializer {
    private static final String LABELS = "labels";
    private static final String LIKE_END_REWARDS = "like_and_rewards";
    private static final String AD = "ad";
    private static final String RELATED_NEWS = "related_news";

    @Override
    public BaseOrderedInfoBean deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        JsonObject jsonObject = json.getAsJsonObject();
        //获取里面的name字段,用作区分的标志
        String name = jsonObject.get("name").getAsString();
        switch (name) {
            case LABELS:
                return new Gson().fromJson(json, OrderedInfoBean1.class);
            case LIKE_END_REWARDS:
                return new Gson().fromJson(json, OrderedInfoBean2.class);
            case AD:
                return new Gson().fromJson(json, OrderedInfoBean3.class);
            case RELATED_NEWS:
                return new Gson().fromJson(json, OrderedInfoBean4.class);
            default:
                return null;
        }
    }
}

最后一步,把整个解析器注册到Gson实例中去:

 Gson gson = new GsonBuilder()
                .registerTypeAdapter(BaseOrderedInfoBean.class, new OrderedInfoDeserializer())
                .create();

由于网络请求采用的是Retrofit,因此需要需要设置一下:

new Retrofit.Builder()addConverterFactory(GsonConverterFactory.create(gson)).create();

这样就能愉快的进行解析了O(∩_∩)O

你可能感兴趣的:(Android Gson解析数组中多种类型)