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

如何通过Gson用方法生成计算属性?@SerializedName注解未生效

Gson序列化抽象类计算属性的解决方案

问题核心:Gson默认仅序列化类的字段,以及符合JavaBean规范的getter方法(以get/is开头的无参方法)。你定义的方法并非get开头,且@SerializedName直接标注在非标准getter方法上默认不生效,因此无法生成目标字段。

以下是几种可行的解决方法:

方法一:修改方法为JavaBean规范的getter形式

将方法名改为get开头的标准getter格式,配合@SerializedName注解,Gson会自动将其识别为属性序列化:

public abstract static class BaseSyncTimedReport extends TimedReport {
    protected Date findOffsetEndTime = new Date();
    protected Date findNextBatchEndTime = new Date();
    protected Date batchSyncEndTime = new Date();

    @SerializedName("findOffsetDuration")
    public long getFindOffsetDuration() {
        return Duration.between(startTime.toInstant(), findOffsetEndTime.toInstant()).toMillis();
    }

    @SerializedName("findNextBatchDuration")
    public long getFindNextBatchDuration() {
        return Duration.between(findOffsetEndTime.toInstant(), findNextBatchEndTime.toInstant()).toMillis();
    }

    @SerializedName("batchSyncDuration")
    public long getBatchSyncDuration() {
        return Duration.between(findNextBatchEndTime.toInstant(), batchSyncEndTime.toInstant()).toMillis();
    }
}

方法二:自定义TypeAdapter手动控制序列化

如果不想修改方法名,可以通过自定义TypeAdapter,在序列化时手动添加计算属性:

Gson gson = new GsonBuilder()
        .registerTypeAdapter(BaseSyncTimedReport.class, new TypeAdapter<BaseSyncTimedReport>() {
            @Override
            public void write(JsonWriter out, BaseSyncTimedReport value) throws IOException {
                out.beginObject();
                // 先序列化原有字段(包括父类字段)
                Gson defaultGson = new Gson();
                JsonObject obj = defaultGson.toJsonTree(value).getAsJsonObject();
                for (Map.Entry<String, JsonElement> entry : obj.entrySet()) {
                    out.name(entry.getKey());
                    defaultGson.toJson(entry.getValue(), out);
                }
                // 手动写入计算属性
                out.name("findOffsetDuration").value(value.findOffsetDuration());
                out.name("findNextBatchDuration").value(value.findNextBatchDuration());
                out.name("batchSyncDuration").value(value.batchSyncDuration());
                out.endObject();
            }

            @Override
            public BaseSyncTimedReport read(JsonReader in) throws IOException {
                // 按需实现反序列化逻辑,若不需要可返回null或抛出异常
                throw new UnsupportedOperationException("反序列化未实现");
            }
        })
        .create();

方法三:将计算属性转为字段并提前计算

把计算属性改为普通字段,在序列化前手动更新字段值:

public abstract static class BaseSyncTimedReport extends TimedReport {
    protected Date findOffsetEndTime = new Date();
    protected Date findNextBatchEndTime = new Date();
    protected Date batchSyncEndTime = new Date();

    @SerializedName("findOffsetDuration")
    protected long findOffsetDuration;

    @SerializedName("findNextBatchDuration")
    protected long findNextBatchDuration;

    @SerializedName("batchSyncDuration")
    protected long batchSyncDuration;

    // 在设置完时间字段后调用,更新计算值
    public void syncDurations() {
        findOffsetDuration = Duration.between(startTime.toInstant(), findOffsetEndTime.toInstant()).toMillis();
        findNextBatchDuration = Duration.between(findOffsetEndTime.toInstant(), findNextBatchEndTime.toInstant()).toMillis();
        batchSyncDuration = Duration.between(findNextBatchEndTime.toInstant(), batchSyncEndTime.toInstant()).toMillis();
    }
}

使用时需在序列化前调用syncDurations()方法,确保字段值已更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 16:31:14