Gson反序列化时如何调用setter方法?2022年推荐替代方案
问题解答
Gson能否配置为反序列化时调用setter方法
Gson原生不支持该能力,也没有提供任何配置开关可以开启反序列化调用setter的行为。它内置的ReflectiveTypeAdapterFactory默认直接通过反射修改类的字段值,会完全绕过所有setter方法,这就是示例代码中Gson解析得到a=1而非预期101的根本原因。
如果一定要在Gson框架内实现setter调用,只能自行实现通用的TypeAdapterFactory,替换Gson默认的反射适配器,在字段赋值逻辑中主动查找匹配的setter方法并调用。但这种方案需要自行处理字段名映射、类型转换、重载方法匹配、访问权限等大量边界问题,实现和维护成本极高,完全不推荐在生产环境使用。
2022年setter自定义赋值逻辑的推荐实现方案
不需要强行改造Gson的前提下,有两个成熟稳定、经过生产验证的方案可选:
- 直接使用Jakarta JSON Binding(JSON-B):即示例中已经引入的Jsonb实现,它本身严格遵循JavaBean访问规范,反序列化时默认优先调用对应字段的public setter方法,写在setter中的值处理逻辑可以直接生效,不需要任何额外配置。
- 改用Jackson:这是当前Java生态普及率最高的JSON处理库,也是Spring技术栈的默认JSON实现。它默认反序列化就会调用字段对应的setter方法,完全兼容setter内的自定义逻辑,性能优异、生态完善,各类场景的解决方案资料非常丰富,是绝大多数Java项目的首选JSON库。
如果受项目依赖限制必须使用Gson,更合理的实现方式是不要把赋值逻辑耦合在setter中等待框架自动调用,而是为对应实体类注册自定义JsonDeserializer,在反序列化逻辑中手动完成数值加工处理,避免自行修改Gson核心反射逻辑带来的版本兼容、性能损耗等问题。
问题复现代码
Controller层代码
@RestController public class NumberController { @RequestMapping("/number") public Number number() { String jsonString = "{\"a\":1}"; // Gson默认实现:直接反射修改字段,绕过setter GsonBuilder builder = new GsonBuilder(); Gson gson = builder.create(); Number numberWithGson = gson.fromJson(jsonString, Number.class); System.out.println(numberWithGson); // 输出 Number(a=1) // Jsonb默认实现:调用setter赋值,自定义逻辑生效 Jsonb jsonb = JsonbBuilder.create(); Number numberWithJsonB = jsonb.fromJson(jsonString, Number.class); System.out.println(numberWithJsonB); // 输出 Number(a=101) return numberWithGson; // 默认返回{"a":1},不符合预期 } }
实体类代码
public class Number { private int a; public void setA(int a) { this.a = a + 100; } // 省略getter、toString方法 }
补充说明:如果使用Jackson替换Gson做反序列化,不需要修改上述实体类的任何代码,直接解析即可得到
a=101的预期结果。
内容的提问来源于stack exchange,提问作者Anne Maier
相关产品推荐
相关产品推荐

