You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Room@Embedded时,如何让Gson将嵌套字段平展至父实体类?

解决方案:结合Room @Embedded与Gson扁平化反序列化

这个需求太常见了!结合Room的嵌套实体存储和Gson的扁平化JSON反序列化,不用自定义JsonAdapter也有很优雅的解决方案,优先推荐用Gson自带的注解来实现,下面给你两种可行的思路:

1. 最优方案:使用Gson的@JsonUnwrapped注解(推荐)

Gson的@JsonUnwrapped注解正好和Room的@Embedded功能对应——它会告诉Gson把嵌套对象的字段直接映射到父对象的JSON层级中,完全符合你的需求。只需要做两个小修改:

修改后的实体类代码

@Entity
public class MyObject {
    // 必须改为静态内部类:Gson默认无法反序列化非静态内部类(依赖外部类实例)
    public static class GeneralInfo {
        public String ownerName;
        @PrimaryKey
        public long wellId;
    }

    @Embedded // Room用来将嵌套类字段嵌入数据表
    @JsonUnwrapped // Gson用来扁平化JSON反序列化/序列化
    public GeneralInfo generalInfo;

    public long objectId;

    // 无参构造函数:Gson反序列化必须要有
    public MyObject() {
        this.generalInfo = new GeneralInfo();
    }

    // 其他字段和业务方法...
}

关键说明

  • @JsonUnwrapped:Gson会自动把JSON中平级的wellId、ownerName直接赋值给generalInfo对象的对应字段,不需要嵌套的generalInfoJSON节点。
  • 静态内部类:非静态内部类依赖外部MyObject实例才能创建,Gson无法自动处理,改成静态内部类后就能正常反序列化了。
  • 无参构造函数:确保Gson能正确实例化MyObject和GeneralInfo对象。

2. 备选方案:手动映射字段的Getter/Setter

如果你因为某些原因不想用@JsonUnwrapped,可以通过添加和JSON字段对应的Getter/Setter,配合Room的@Ignore注解来实现:

代码示例

@Entity
public class MyObject {
    public static class GeneralInfo {
        public String ownerName;
        @PrimaryKey
        public long wellId;
    }

    @Embedded
    public GeneralInfo generalInfo = new GeneralInfo();

    public long objectId;

    // Gson直接映射JSON中的ownerName,Room忽略这个方法
    @Ignore
    @SerializedName("ownerName")
    public void setOwnerName(String ownerName) {
        this.generalInfo.ownerName = ownerName;
    }

    // Gson直接映射JSON中的wellId,Room忽略这个方法
    @Ignore
    @SerializedName("wellId")
    public void setWellId(long wellId) {
        this.generalInfo.wellId = wellId;
    }

    // 可选:添加Getter让Gson序列化时也能输出平级字段
    @Ignore
    @SerializedName("ownerName")
    public String getOwnerName() {
        return this.generalInfo.ownerName;
    }

    @Ignore
    @SerializedName("wellId")
    public long getWellId() {
        return this.generalInfo.wellId;
    }

    public MyObject() {}
}

关键说明

  • @SerializedName:告诉Gson这些Getter/Setter对应JSON中的平级字段。
  • @Ignore:告诉Room不要把这些方法当成实体类的字段,避免生成多余的数据表列。
  • 这种方法更灵活,但代码量比第一种方案多,适合需要自定义字段映射逻辑的场景。

内容的提问来源于stack exchange,提问作者Mneckoee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:03:52