Java GSON将多个属性序列化到子对象

Java GSON将多个属性序列化到子对象,java,android,gson,retrofit,Java,Android,Gson,Retrofit,在我的项目中,我一直在尝试改型和GSON,遇到了一个不寻常的情况,我试图在Android上使用GSON将两个属性从JSON转换为子对象 JSON示例: { "cat1_id": "1111", "cat1_name": "First Category", "cat2_id": "2222", "cat2_name": "Second Category", } 下面是一些典型的例子,看起来人们通常会创建这样的类 public class InventoryItem {

在我的项目中,我一直在尝试改型和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,改型后可以作为响应,然后使用for循环将其转换为我更喜欢的格式。但这似乎违背了GSON的全部目的。

我建议采用两种方法

让一个类充当桥接器 只需重新定义初始的
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);
    }
}
并使用它:

InventoryItem inventoryItem = gson.fromJson(json, InventoryItem.class);
这将产生与以前相同的输出。当然,反序列化程序可能不那么具体(例如,通过迭代对象的条目集)。这应该会给你一些见解


希望有帮助!:)

以下是我正在测试的一个解决方案示例,以供将来参考

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;
    }
}
公共类InventoryItemDeserializer实现JsonDeserializer{
private static final Gson Gson=new GsonBuilder().create();
@凌驾
公共InventoryItem反序列化(JsonElement json,类型typeOfT,JsonDeserializationContext)引发JsonParseException{
JsonObject jObject=json.getAsJsonObject();
InventoryItem=GSON.fromJson(json,InventoryItem.class);
item.setCategory(新类别(jObject.get(“cat1_id”).getAsInt(),jObject.get(“cat1_name”).getAsString());
item.setSubCategory(新类别(jObject.get(“cat2_id”).getAsInt(),jObject.get(“cat2_name”).getAsString());
item.setFinalCategory(新类别(jObject.get(“cat3_id”).getAsInt(),jObject.get(“cat3_name”).getAsString());
退货项目;
}
}

如果使用自定义反序列化程序,是否需要手动告诉它如何执行所有操作?或者我可以只指定类别。(当然,我还有其他领域需要担心。)@Hackmodford我不确定我是否明白你的真正意思。但是,是的,当JSON表示一个
InventoryItem
时,您可以指定要反序列化的内容。根据结构的不同,您可以或多或少地跳过想要保留或不保留的内容。我希望Gson能够自动完成大部分工作,并且只自定义反序列化类别信息。我想我有一个解决办法。(见我的回答)你对此有何评论?
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;
    }
}