zoukankan      html  css  js  c++  java
  • 使用GSON和泛型解析约定格式的JSON串(转)

    时间紧张,先记一笔,后续优化与完善。

    解决的问题:

          使用GSON和泛型解析约定格式的JSON串。

    背景介绍:

           1.使用GSON来进行JSON串与java代码的互相转换。

           2.JSON的格式如下三种:

             

    写道
    #第一种:
    {"success":true,"data":{"averageStarLevel":4.7,"remarkCount":10}}
    #第二种:
    {"success":true,"data":{"page":10,"pageCount":29,"list":[{"starLevel":4,"remarkCotnent":"评价方未及时做出评价,系统默认满意!","remarkTime":"2013-02-27 07:21:48","explainContent":"","postMemberId":"y**f","tpLogoURL":"http://i04.c.aliimg.com/cms/upload/2012/186/684/486681_1232736939.png"},{"starLevel":4,"remarkCotnent":"评价方未及时做出评价,系统默认满意!","remarkTime":"2013-02-27 07:21:48","explainContent":"","postMemberId":"y**f","tpLogoURL":"http://i04.c.aliimg.com/cms/upload/2012/186/684/486681_1232736939.png"}],"statistics":{"star5":20,"star4":40,"star3":30,"star2":10,"star1":0}}}
    #第三种:{"success":true,"data":[{"starLevel":4,"remarkCotnent":"评价方未及时做出评价,系统默认满意!","remarkTime":"2013-02-27 07:21:48","explainContent":"","postMemberId":"y**f","tpLogoURL":"http://i04.c.aliimg.com/cms/upload/2012/186/684/486681_1232736939.png"},{"starLevel":4,"remarkCotnent":"评价方未及时做出评价,系统默认满意!","remarkTime":"2013-02-27 07:21:48","explainContent":"","postMemberId":"y**f","tpLogoURL":"http://i04.c.aliimg.com/cms/upload/2012/186/684/486681_1232736939.png"}]}

    分析:

         在工作时间中,遇到一种场景,就是在应用中调用多个JSON接口,各接口返回的数据内容不一样,如果逐一解析代码会比较臃肿。JSON串如上所列有三种基本格式。经过分析,发现三种JSON串有一个共同的特点。JSON结构一致:

    写道
    {"success":true,"data":##} 

    success:代表是否访问成功

        data:后面跟着所需信息.

       

        基本相同的JSON结构,所以想定义一种通用模型对应到此结构。但是,data中的数据类型不一致。如第一种是简单对象,第二种是对象中嵌套数组,第三种是List。针对data数据类型不一致的情况,使用泛型来解决。

    import java.io.Serializable;
    import java.lang.reflect.ParameterizedType;
    import java.lang.reflect.Type;
    
    import com.google.gson.Gson;
    
    public class CommonJson<T> implements Serializable {
    
        /**
         *
         */
        private static final long serialVersionUID = -3440061414071692254L;
    
        /**
         * 是否成功
         */
        private Boolean success;
    
        /**
         * 数据
         */
        private T data;
    
        public Boolean getSuccess() {
            return success;
        }
    
        public void setSuccess(Boolean success) {
            this.success = success;
        }
    
        public T getData() {
            return data;
        }
    
        public void setData(T data) {
            this.data = data;
        }
    }

     GSON对于泛型的支持不足,为了使GSON对于泛型进行解析,JSON解析与组装代码如下:

           public static CommonJson fromJson(String json, Class clazz) {
            Gson gson = new Gson();
            Type objectType = type(CommonJson.class, clazz);
            return gson.fromJson(json, objectType);
        }
    
        public String toJson(Class<T> clazz) {
            Gson gson = new Gson();
            Type objectType = type(CommonJson.class, clazz);
            return gson.toJson(this, objectType);
        }
    
        static ParameterizedType type(final Class raw, final Type... args) {
            return new ParameterizedType() {
                public Type getRawType() {
                    return raw;
                }
    
                public Type[] getActualTypeArguments() {
                    return args;
                }
    
                public Type getOwnerType() {
                    return null;
                }
            };
        }

     以上两段代码可以满足第一种和第二种JSON的解析,对于第三种,data是List类型的,无法得到List<>的class,所以,针对第三种格式,实现代码如下:

    import java.io.Serializable;
    import java.lang.reflect.ParameterizedType;
    import java.lang.reflect.Type;
    import java.util.List;
    
    import com.google.gson.Gson;
    
    public class CommonJson4List<T> implements Serializable {
    
        /**
         *
         */
        private static final long serialVersionUID = -369558847578246550L;
    
        /**
         * 是否成功
         */
        private Boolean success;
    
        /**
         * 数据
         */
        private List<T> data;
    
        public Boolean getSuccess() {
            return success;
        }
    
        public void setSuccess(Boolean success) {
            this.success = success;
        }
    
        public List<T> getData() {
            return data;
        }
    
        public void setData(List<T> data) {
            this.data = data;
        }
    
        public static CommonJson4List fromJson(String json, Class clazz) {
            Gson gson = new Gson();
            Type objectType = type(CommonJson4List.class, clazz);
            return gson.fromJson(json, objectType);
        }
    
        public String toJson(Class<T> clazz) {
            Gson gson = new Gson();
            Type objectType = type(CommonJson4List.class, clazz);
            return gson.toJson(this, objectType);
        }
    
        static ParameterizedType type(final Class raw, final Type... args) {
            return new ParameterizedType() {
                public Type getRawType() {
                    return raw;
                }
    
                public Type[] getActualTypeArguments() {
                    return args;
                }
    
                public Type getOwnerType() {
                    return null;
                }
            };
        }
    
    }

    测试代码如下:

    import java.util.ArrayList;
    import java.util.List;
    
    import com.alibaba.asc.sharewood.common.http.CommonJson;
    import com.alibaba.asc.sharewood.common.http.CommonJson4List;
    import com.alibaba.asc.sharewood.external.service.model.AverageStarLevelAndCount;
    import com.alibaba.asc.sharewood.external.service.model.Evalution;
    import com.alibaba.asc.sharewood.external.service.model.EvalutionProfile;
    import com.alibaba.asc.sharewood.external.service.model.StarLevelStatistics;
    
    public class Test {
    
        @SuppressWarnings("unchecked")
        public static void main(String[] args) {
    
            CommonJson<AverageStarLevelAndCount> cj = new CommonJson<AverageStarLevelAndCount>();
            AverageStarLevelAndCount data = new AverageStarLevelAndCount();
            data.setAverageStarLevel(4.7f);
            data.setRemarkCount(10);
    
            cj.setSuccess(Boolean.TRUE);
            cj.setData(data);
    
            String res1 = cj.toJson(AverageStarLevelAndCount.class);
    
            System.out.println(res1);
    
            CommonJson<AverageStarLevelAndCount> cj2 = CommonJson.fromJson(res1,
                    AverageStarLevelAndCount.class);
    
            System.out.println(cj2.getSuccess());
            System.out.println(cj2.getData().getAverageStarLevel());
    
            EvalutionProfile p = new EvalutionProfile();
            p.setPage(10);
            p.setPageCount(29);
    
            StarLevelStatistics s = new StarLevelStatistics();
            s.setStar1(0);
            s.setStar2(10);
            s.setStar3(30);
            s.setStar4(40);
            s.setStar5(20);
    
            p.setStatistics(s);
    
            Evalution e1 = new Evalution();
    
            e1.setStarLevel(4);
            e1.setRemarkTime("2013-02-27 07:21:48");
            e1.setRemarkCotnent("评价方未及时做出评价,系统默认满意!");
            e1.setTpLogoURL("http://i04.c.aliimg.com/cms/upload/2012/186/684/486681_1232736939.png");
            e1.setExplainContent("");
            e1.setPostMemberId("y**f");
    
            Evalution e2 = new Evalution();
    
            e2.setStarLevel(4);
            e2.setRemarkTime("2013-02-27 07:21:48");
            e2.setRemarkCotnent("评价方未及时做出评价,系统默认满意!");
            e2.setTpLogoURL("http://i04.c.aliimg.com/cms/upload/2012/186/684/486681_1232736939.png");
            e2.setExplainContent("");
            e2.setPostMemberId("y**f");
    
            List<Evalution> le = new ArrayList<Evalution>();
            le.add(e1);
            le.add(e2);
    
            p.setList(le);
    
            CommonJson<EvalutionProfile> ce = new CommonJson<EvalutionProfile>();
    
            ce.setSuccess(Boolean.TRUE);
            ce.setData(p);
    
            String res2 = ce.toJson(EvalutionProfile.class);
    
            System.out.println(res2);
    
            String ps = "{"data":{"pageCount":29,"page":"1","list":[{"starLevel":4,"remarkTime":"2013-04-10 05:17:42","explainTime":"","remarkContent":"评价方未及时做出评价,系统默认满意!","tpLogoURL":"","explainContent":"","postMemberId":"b**6"},{"starLevel":4,"remarkTime":"2013-04-05 04:42:40","explainTime":"","remarkContent":"评价方未及时做出评价,系统默认满意!","tpLogoURL":"","explainContent":"","postMemberId":"b**8"},{"starLevel":4,"remarkTime":"2013-03-20 00:52:18","explainTime":"","remarkContent":"评价方未及时做出评价,系统默认满意!","tpLogoURL":"","explainContent":"","postMemberId":"b**5"},{"starLevel":4,"remarkTime":"2013-03-07 01:51:01","explainTime":"","remarkContent":"评价方未及时做出评价,系统默认满意!","tpLogoURL":"","explainContent":"","postMemberId":"b**7"},{"starLevel":4,"remarkTime":"2013-03-06 03:38:57","explainTime":"","remarkContent":"评价方未及时做出评价,系统默认满意!","tpLogoURL":"","explainContent":"","postMemberId":"z**2"},{"starLevel":4,"remarkTime":"2013-03-06 03:17:33","explainTime":"","remarkContent":"评价方未及时做出评价,系统默认满意!","tpLogoURL":"","explainContent":"","postMemberId":"b**2"},{"starLevel":4,"remarkTime":"2013-03-03 01:40:17","explainTime":"","remarkContent":"评价方未及时做出评价,系统默认满意!","tpLogoURL":"","explainContent":"","postMemberId":"a**6"},{"starLevel":4,"remarkTime":"2013-03-01 02:41:31","explainTime":"","remarkContent":"评价方未及时做出评价,系统默认满意!","tpLogoURL":"","explainContent":"","postMemberId":"b**4"},{"starLevel":4,"remarkTime":"2013-02-28 03:20:45","explainTime":"","remarkContent":"评价方未及时做出评价,系统默认满意!","tpLogoURL":"","explainContent":"","postMemberId":"t**y"},{"starLevel":4,"remarkTime":"2013-02-27 07:21:48","explainTime":"","remarkContent":"评价方未及时做出评价,系统默认满意!","
                    + ""tpLogoURL":""
                    + "http://i04.c.aliimg.com/cms/upload/2012/186/684/486681_1232736939.png","explainContent":"","postMemberId":"y**f"}],"
                    + ""statistics":{"star5":59,"star4":38,"star3":2,"star2":1,"star1":0}},"success":true}";
    
            CommonJson<EvalutionProfile> re = CommonJson.fromJson(ps,
                    EvalutionProfile.class);
    
            System.out.println(re.getData().getStatistics().getStar5());
    
            System.out.println(re.getData().getPageCount());
    
            System.out.println(re.getData().getList().get(0).getPostMemberId());
    
            CommonJson4List<Evalution> cjl = new CommonJson4List<Evalution>();
    
            cjl.setSuccess(Boolean.TRUE);
            cjl.setData(le);
    
            System.out.println("###" + cjl.toJson(Evalution.class));
    
            String sList = "{"data":[{"starLevel":4,"remarkCotnent":"评价方未及时做出评价,系统默认满意!","remarkTime":"2013-02-27 07:21:48","explainContent":"","postMemberId":"y**f","tpLogoURL":"http://i04.c.aliimg.com/cms/upload/2012/186/684/486681_1232736939.png"},{"starLevel":4,"remarkCotnent":"评价方未及时做出评价,系统默认满意!","remarkTime":"2013-02-27 07:21:48","explainContent":"","postMemberId":"y**f","tpLogoURL":"http://i04.c.aliimg.com/cms/upload/2012/186/684/486681_1232736939.png"}],"success":true}";
    
            CommonJson4List<Evalution> cjle = CommonJson4List.fromJson(sList,
                    Evalution.class);
    
            System.out.println("***"
                    + cjle.getData().get(0).getPostMemberId());
    
        }
    }

    执行结果如下:

    {"success":true,"data":{"averageStarLevel":4.7,"remarkCount":10}}
    true
    4.7
    {"success":true,"data":{"page":10,"pageCount":29,"list":[{"starLevel":4,"remarkCotnent":"评价方未及时做出评价,系统默认满意!","remarkTime":"2013-02-27 07:21:48","explainContent":"","postMemberId":"y**f","tpLogoURL":"http://i04.c.aliimg.com/cms/upload/2012/186/684/486681_1232736939.png"},{"starLevel":4,"remarkCotnent":"评价方未及时做出评价,系统默认满意!","remarkTime":"2013-02-27 07:21:48","explainContent":"","postMemberId":"y**f","tpLogoURL":"http://i04.c.aliimg.com/cms/upload/2012/186/684/486681_1232736939.png"}],"statistics":{"star5":20,"star4":40,"star3":30,"star2":10,"star1":0}}}
    59
    29
    b**6
    {"success":true,"data":[{"starLevel":4,"remarkCotnent":"评价方未及时做出评价,系统默认满意!","remarkTime":"2013-02-27 07:21:48","explainContent":"","postMemberId":"y**f","tpLogoURL":"http://i04.c.aliimg.com/cms/upload/2012/186/684/486681_1232736939.png"},{"starLevel":4,"remarkCotnent":"评价方未及时做出评价,系统默认满意!","remarkTime":"2013-02-27 07:21:48","explainContent":"","postMemberId":"y**f","tpLogoURL":"http://i04.c.aliimg.com/cms/upload/2012/186/684/486681_1232736939.png"}]}
    y**f

    Ps:文中说到Gson对泛型的支持不足,其实是不正确的,Gson对泛型做了以下支持:

    public static CommonJson4List fromJson(String json, Class clazz) {  
            Gson gson = new Gson();  
            Type objectType = new TypeToken<CommonJson4List<clazz>>() {}.getType();  
            return gson.fromJson(json, objectType);  
        }  

    只需将获取类型的泛型类作为TypeToken的泛型参数构造一个匿名的子类,就可以通过getType方法获取一个parameterized类型,结果与type方法一致。

  • 相关阅读:
    MyBatis中#{}和${}的区别
    springBoot 配置详解
    模板方法模式
    记录一次linux挂载数据盘
    缓存击穿,缓存穿透,缓存雪崩
    Echart折线值相加问题
    mybatis plus主键生成策略
    BigDecimal精度损失
    cent0s6安装nginx小程序https
    Centos6 java运行环境部署
  • 原文地址:https://www.cnblogs.com/qq78292959/p/3781808.html
Copyright © 2011-2022 走看看