【问题标题】:GSON serialize multiple properties to sub objectGSON 将多个属性序列化为子对象
【发布时间】:2015-11-26 03:45:31
【问题描述】:

我一直在我的项目中尝试使用 Retrofit 和 GSON,遇到了一个不寻常的情况,我试图在 Android 上使用 GSON 将两个属性从 JSON 转换为子对象。

示例 JSON:

{
  "cat1_id": "1111",
  "cat1_name": "First Category",
  "cat2_id": "2222",
  "cat2_name": "Second Category",
}

按照典型示例,似乎通常会创建这样的类。

public class InventoryItem {

     private int    cat1_id;
     private String cat1_name;
     private int    cat2_id;
     private String cat2_id;

}

但是,我宁愿做这样的事情。

public class InventoryItem {

    private Category category1;
    private Category category2;
}

public class Category {
    private int    id;
    private String name;
}

有没有办法使用 GSON 来实现这一点?我一直在考虑创建一个 POJO,Retrofit 可以将其用作响应,然后使用 for 循环将其转换为我更喜欢的格式。但这似乎违背了 GSON 的全部目的。

【问题讨论】:

    标签: java android gson retrofit


    【解决方案1】:

    我建议两种方法。

    让班级充当桥梁建设者

    只需重新定义您的初始InventoryItem 类,使其充当InventoryItemBuilder 的构建器。

    class InventoryItemBuilder {
        @SerializedName("cat1_id")   private int    catOneId;
        @SerializedName("cat1_name") private String catOneName;
        @SerializedName("cat2_id")   private int    catTwoId;
        @SerializedName("cat2_name") private String catTwoName;
    
        public InventoryItem buildInventoryItem() {
            Category c1 = new Category(catOneId, catOneName);
            Category c2 = new Category(catTwoId, catTwoName);
            return new InventoryItem(c1, c2);
        }
    }
    

    那么你只需在将 JSON 反序列化为 ItemHolder 实例后调用 buildInventoryItem() 方法即可:

    //InventoryItem{category1=Category{id=1111, name='First Category'}, category2=Category{id=2222, name='Second Category'}}
    InventoryItem inventoryItem = new Gson().fromJson(json, InventoryItemBuilder.class).buildInventoryItem();
    

    实现自定义反序列化器

    只需告诉解析器您想如何反序列化您描述的 JSON 实体即可:

    class InventoryItemDeserializer implements JsonDeserializer<InventoryItem> {
        @Override
        public InventoryItem deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
            JsonObject jObject = json.getAsJsonObject();
            Category c1 = new Category(jObject.get("cat1_id").getAsInt(), jObject.get("cat1_name").getAsString());
            Category c2 = new Category(jObject.get("cat2_id").getAsInt(), jObject.get("cat2_name").getAsString());
            return new InventoryItem(c1, c2);
        }
    }
    

    然后在解析器中注册:

    Gson gson = new GsonBuilder().registerTypeAdapter(InventoryItem.class, new InventoryItemDeserializer()).create();
    

    并使用它:

    InventoryItem inventoryItem = gson.fromJson(json, InventoryItem.class);
    

    这会产生与以前相同的输出。当然,反序列化器可能不太具体(例如通过迭代对象的条目集)。这应该会给你一些见解。

    希望对您有所帮助! :)

    【讨论】:

    • 如果我使用自定义解串器,我是否必须手动告诉它如何做所有事情?或者我可以只指定类别。 (当然,我还有其他领域需要担心。)
    • @Hackmodford 我不确定我明白你的意思。但是是的,当 JSON 表示 InventoryItem 时,您可以指定要反序列化的内容。根据结构,您可以或多或少轻松地跳过您想要保留或不保留的内容。
    • 我希望 Gson 自动完成大部分工作,并且只自定义反序列化类别信息。我想我有一个解决办法。 (见我的回答)你有什么相关的吗?
    【解决方案2】:

    为了将来参考,下面是我正在测试的解决方案示例。

    public class InventoryItem {
    
        @SerializedName("AUTO")     private int mPersistentId;
        @SerializedName("ID")       private String mItemId;
        @SerializedName("BARCODE")  private String mBarcode;
        @SerializedName("ALIAS")    private String mAlias;
        @SerializedName("ALIAS2")   private String mAlias2;
        @SerializedName("NAME")     private String mDescription;
    
        private Category mCategory;
        private Category mSubCategory;
        private Category mFinalCategory;
    }
    

    这是我的自定义反序列化器

    public class InventoryItemDeserializer implements JsonDeserializer<InventoryItem> {
    
        private static final Gson GSON = new GsonBuilder().create();
    
        @Override
        public InventoryItem deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
    
            JsonObject jObject = json.getAsJsonObject();
            InventoryItem item = GSON.fromJson(json, InventoryItem.class);
    
            item.setCategory(new Category(jObject.get("cat1_id").getAsInt(), jObject.get("cat1_name").getAsString()));
            item.setSubCategory(new Category(jObject.get("cat2_id").getAsInt(), jObject.get("cat2_name").getAsString()));
            item.setFinalCategory(new Category(jObject.get("cat3_id").getAsInt(), jObject.get("cat3_name").getAsString()));
    
            return item;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-09
      • 1970-01-01
      相关资源
      最近更新 更多