zoukankan      html  css  js  c++  java
  • Gson解析数组多类型元素

    本文的出现是为了解决以下需求:使用Gsonjson数组进行解析,但是数组里面元素的类型是多种的。数据如下:

    {"list":[{
        "type":0,
        "data":{
            "id":1,
            "color":"red"
        }
    },{
        "type":1,
        "data":{
            "id":1,
            "name":"case"
        }
    }]}

    可能你会说data中的对应的实体可以包括所有data中的字段就可以了,那么你采用这种方法我只能说太low了,不是不可以这么做,要是遇到很庞大的实体类,那么你会发现里面甚至需要上百个字段。我们这里举例只是为了说明方便,所以给的数据都比较简单,重在思路。

    如何设计

    为了解决上面的问题,那么我想到的是三种处理方法:

    方法一:也就是上文所说的那种很low的做法咯,把所有的字段都放在一个实体类中。

    这种方法对应初级选手确实感觉还不错,不用思考太多就可以解决解析问题,不过这不是我们程序员应该满足的。(上文已经吐槽过了) 

    方法二:对于数组中data数据结构不同,那么字段就不统一命名成data,而是根据实的结构服务器返回不同的字段,如:colorEntityuserEntity。那么对应的实体类应该是这样的形式:

    public class ListEntity{
    
      int type;
    
      User userEntity;
    
      Color colorEntity;
    
    }

    缺点很明显。①没有统一的数据字段;②添加新类型,服务器加字段需要检查新加字段名不能和已有的字段名重复(如何已有的类型多,那么服务器工作就需要更细心);③Gson对应的解析实体类会因为list结构丰富而变得很庞大,因为每种类型都需要一个对应的字段。 

    当然优点也很明显。简单易懂,遇到问题很容易处理,可读性强。

    此方法前提条件就是需要服务器配合,要是你用现成的服务器那么这种方法完全就不用考虑了。 

    方法三:根据不同的type返回不同的data值(也就是现在示例中的样子),添加Gson解析器来完成解析(可能很多童鞋对此感到很陌生,其实很简单)。

    这种方法就需要对Gson的解析有一定了解。本文也是重点解说如何设计这种解析并且给出demo,下文就是对此方法进行讲解。

    1Gson对应的实体类

    首先我们知道ArrayList里面的元素都是相同的类型,那么如何才能使用不同的类型呢?当然就是集合里面的元素使用一个基类,然后具体的实体类都继承这个基类。示例:

    我们有3个类:

     这个类就是刚刚说的基类,所有list字段里面对应实体的基类

    public class TypeSuper {
    
    }

    list字段里面对应的其中一种类型TypeA

    public class TypeA extends TypeSuper {
    
    public int id;
    
    public String name;
    
     
    
    public TypeA(int id, String name) {
    
    super();
    
    this.id = id;
    
    this.name = name;
    
    }
    
    }

    list字段里面对应的其中另一种类型TypeB

    public class TypeB extends TypeSuper { 
    
      public int id;
    
      public String color;
    
     
      public TypeB(int id, String color) {
    
        super();
    
        this.id = id;
    
        this.color = color;
    
      }
    
    }
     

    Gson对应的实体类TypeResult

    public class TypeResult {
    
    List<TypeSuper> data = new ArrayList<TypeSuper>();
    
    }

     

    2、Gson反序列化

    根据json字符串进行解析,示例代码如下:

    Gson解析器TypeResultDeserializer 

    public class TypeResultDeserializer implements JsonDeserializer<TypeResult> {
    
        @Override
        public TypeResult deserialize(JsonElement arg0, Type arg1,
                JsonDeserializationContext arg2) throws JsonParseException {
            JsonObject obj = arg0.getAsJsonObject();
            JsonArray asJsonArray = obj.get("list").getAsJsonArray();
            TypeResult result = new TypeResult();
            for (JsonElement jsonElement : asJsonArray) {
                JsonObject jsonOb = jsonElement.getAsJsonObject();
                int type = jsonOb.get("type").getAsInt();
                if (type == 0) {
                    JsonObject child = jsonOb.get("data").getAsJsonObject();
                    int id = child.get("id").getAsInt();
                    String name = child.get("color").getAsString();
                    result.data.add(new TypeB(id, name));
                } else if(type == 1) {
                    JsonObject child = jsonOb.get("data").getAsJsonObject();
                    int id = child.get("id").getAsInt();
                    String name = child.get("color").getAsString();
                    result.data.add(new TypeA(id, name));
                }
            }
            return result;
        }
    }


    3、使用解析器解析Demo

    public class Test {
    
        public static void main(String[] args) {
            GsonBuilder gsonb = new GsonBuilder();
            gsonb.registerTypeAdapter(TypeResult.class, new TypeResultDeserializer());
            gsonb.serializeNulls();
            Gson gson = gsonb.create();
            String json = "{"list":[{" + ""type":0," + ""data":{"
                    + ""id":1," + ""color":"red"" + "}" + "},{"
                    + ""type":1," + ""data":{" + ""id":1,"
                    + ""color":"case"" + "}" + "}]}";
            List<TypeSuper> item = gson.fromJson(json, TypeResult.class).data;
            for (TypeSuper baseItem : item) {
                if (baseItem instanceof TypeA) {
                    System.out.println(((TypeA) baseItem).name);
                } else if (baseItem instanceof TypeB) {
                    System.out.println(((TypeB) baseItem).color);
                }
            }
        }
    }

    看完整个步骤,最核心的就是自定义解析器,根据自己的需求进行解析。以上就完整解说了方式三的具体操作流程。如果读者有更好的方式解析希望可以分享一下。 

    如果文中有任何疑问或者不妥之处欢迎留言交流。在此也留下QQ群311536202,欢迎交流。

  • 相关阅读:
    bzoj 1697: [Usaco2007 Feb]Cow Sorting牛排序【置换群】
    【20】AngularJS 参考手册
    【19】AngularJS 应用
    【18】AngularJS 包含
    【17】AngularJS Bootstrap
    【16】AngularJS API
    【15】AngularJS 输入验证
    【14】AngularJS 表单
    【13】AngularJS 模块
    【12】AngularJS 事件
  • 原文地址:https://www.cnblogs.com/vanezkw/p/4920837.html
Copyright © 2011-2022 走看看