如何通过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
相关产品推荐
相关产品推荐

