【问题标题】:Retrofit best practice, custom gson deserializer改造最佳实践,自定义 gson 反序列化器
【发布时间】:2016-02-21 12:50:50
【问题描述】:

我有一个关于如何通过改造来执行这种反序列化的问题。

我有一个复杂的 Json 需要解析:

{
  "key":"value",
  "rows" : [
    {  //type 1 object
      "type" : "the_type_1",
      "self" :{
          //type 1 subobject
      }
    },
    {  //type 2 object
      "type" : "the_type_2",
      "self" : {
          //type 2 subobject
      }
    },
    { //type 3 object
      "type" : "the_type_3",
      "self" : {  //type 2 object with different key
        "type" : "the_type_2",
         "target":{
            //type 2 subobject
         }
      }
    }
  ]
}

我的每一行都可以有非常不同的内容框架,我已经简化了它,但是你可以看到我有嵌套的对象,这些对象的一些键在函数中改变了它在 json 中的深度。

所以我的第一个解决方案是构建包含每种可能性的每个键的巨大 Gson 模型,然后测试“类型”类型的字段以了解要访问的内容。但它非常难以维护,因此并不优雅。

我想我可以使用 Gson Stream mode 和自定义改造转换器做点什么,但我不知道从哪里开始,也不知道这是否是正确的方法。

你会怎么做?

另外,我的帖子标题不好,因为我没有提出更好的建议。

谢谢,

【问题讨论】:

    标签: android gson retrofit json-deserialization


    【解决方案1】:

    更新

    制作这个类

    public class Target {
    
    }
    

    制作这个Self.java

    import com.google.gson.annotations.SerializedName;
    
    public class Self {
    
        @SerializedName("type")
        private String type;
    
        @SerializedName("target")
        private Target target;
    
        public String getType() {
            return type;
        }
    
        public void setType(String type) {
            this.type = type;
        }
    
        public Target getTarget() {
            return target;
        }
    
        public void setTarget(Target target) {
            this.target = target;
        }
    }
    

    创建一个Row.java

    import com.google.gson.annotations.SerializedName;
    
    public class Row {
    
        @SerializedName("type")
        private String type;
    
        @SerializedName("self")
        private Self self;
    
        public String getType() {
            return type;
        }
    
        public void setType(String type) {
            this.type = type;
        }
    
        public Self getSelf() {
            return self;
        }
    
        public void setSelf(Self self) {
            this.self = self;
        }
    }
    

    这是Respones.java,将使用 gson 进行序列化

    import java.util.ArrayList;
    
    import com.google.gson.annotations.SerializedName;
    
    public class Respones {
    
        @SerializedName("key")
        private String key;
    
        @SerializedName("rows")
        private ArrayList<Row> rows;
    
        public String getKey() {
            return key;
        }
    
        public void setKey(String key) {
            this.key = key;
        }
    
        public ArrayList<Row> getRows() {
            return rows;
        }
    
        public void setRows(ArrayList<Row> rows) {
            this.rows = rows;
        }
    }
    

    以下是检查类是否正常工作的测试代码,

    您可以在代码中使用上述模型类,但以下代码严格匹配您的数据,这绝不是生成JSON 数据的标准方式,您要如何填充对象取决于您

    import java.util.ArrayList;
    
    import com.google.gson.Gson;
    
    public class TestDrive {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            Respones respones = new Respones();
            respones.setKey("value");
            ArrayList<Row> rows = new ArrayList<>();
            Row one = new Row();
            one.setType("the_type_1");
            one.setSelf(new Self());
    
            Row two = new Row();
            two.setType("the_type_2");
            two.setSelf(new Self());
    
            Row three = new Row();
            three.setType("the_type_3");
            Self self = new Self();
            self.setTarget(new Target());
            self.setType("the_type_2");
            three.setSelf(self);
            rows.add(one);
            rows.add(two);
            rows.add(three);
            respones.setRows(rows);
    
        /**
         * This code will convert your ArrayList object to a equivalent JSON
         * String
         */
        String result = (new Gson()).toJson(respones);
        System.out.println(""+result);
    
    
        /**
         * This code will convert your JSON String to a equivalent Response
         * Object
         */
        Respones respones2 = (new Gson()).fromJson(result, Respones.class);
        System.out.println(""+respones2.getKey());
        System.out.println(""+respones2.getRows().get(0).getType());
        System.out.println(""+respones2.getRows().get(2).getSelf().getType());
        }
    }
    

    输出

    {
      "key": "value",
      "rows": [
        {
          "type": "the_type_1",
          "self": {
    
          }
        },
        {
          "type": "the_type_2",
          "self": {
    
          }
        },
        {
          "type": "the_type_3",
          "self": {
            "type": "the_type_2",
            "target": {
    
            }
          }
        }
      ]
    }
    
    value
    the_type_1
    the_type_2
    

    【讨论】:

    • 您好,感谢您抽出宝贵时间准确地回答我。我不能用改造来做到这一点,我无权访问原始 json。另请注意,我正在尝试从 json 创建 pojo,而不是相反。
    • @RenaudFavier,嗯,我明白了,上面我发布的代码实际上需要程序员知道 JSON 的结构,其中键将由 Java 类中的属性表示,我不知道 Pojo 是如何工作的,但我想知道很多人都在使用它,实际上这段代码可用于阅读您发布的以下 JSON 将填充您的对象,我将更新答案,以便您看到它
    • @RenaudFavier,我检查了 POJO 是什么,我可以说你最好使用我提供的代码。但是如果你想拥有 POJO 你可以让类的所有实例变量 public 删除 getter 和 setter 因为你不需要它们并删除注释,你会得到 POJO 你想退出我写的课程。
    • 嗨,POJO 我只是指 Java 对象。我已经做了一个自定义解析器,它工作正常(我使用 gson 流模式),问题是与改造的集成。而且您的代码与我想要的相反(从 json 到 java 对象)
    • @RenaudFavier,你的意思是你想要像 Java 对象这样的东西来 JSON
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多