移除Lombok的@Getter注解后第三方REST API请求字段为何为空?
我正在调用第三方REST端点,预期的请求结构如下:
{ "body": { "accountNumber": "12345" }, "header": { "username": "someusername", "password": "somepassword" } }
我创建了3个Bean类:
MyRequest.java
@Builder @JsonDeserialize(builder = MyRequest.MyRequestBuilder.class) public class MyRequest { @JsonProperty("header") private MyHeader header; @JsonProperty("body") private MyBody body; }
MyBody.java
@Getter @Builder public class MyBody { private String accountNumber; }
MyHeader.java
@Getter @Builder public class MyHeader { private String username; private String password; }
我通过以下代码构建请求对象:
MyBody body = MyBody.builder().accountNumber("12345").build(); MyHeader header = MyHeader.builder().username("someusername").password("somepassword").build(); MyRequest request = MyRequest.builder().body(body).header(header).build();
调用第三方接口的代码如下:
HttpEntity<MyRequest> httpEntity = new HttpEntity<>(myRequest, httpHeaders); String url = "someurl"; someResponse = this.restTemplate.postForObject(url, httpEntity, SomeResponse.class);
原本接口能正常返回响应,但移除MyHeader和MyBody上的@Getter注解后,第三方收到的请求字段全为null。请问:
- 为什么
@Getter是必需的? - 如何在不使用
@Getter的情况下解决这个问题?
一、为什么@Getter是必需的?
你用的RestTemplate默认依赖Jackson来把Java对象序列化成JSON。Jackson序列化私有字段的默认逻辑是:
- 优先找对应字段的Getter方法(比如
getAccountNumber()对应accountNumber字段),通过Getter读取字段值; - 如果没有Getter,Jackson会尝试直接访问私有字段,但这个权限默认是关闭的。
你的MyHeader和MyBody里的字段都是private修饰的,移除@Getter后,Jackson找不到读取字段的途径,又没权限直接访问私有字段,所以序列化出来的JSON里这些字段都是null,第三方自然收到空值。
另外要注意:Lombok的@Builder只会生成构建器和全参构造方法,不会自动生成Getter,所以去掉@Getter后,类里完全没有能让Jackson获取字段值的入口。
二、不使用@Getter的解决办法
有几种可行的替代方案:
1. 配置Jackson允许直接访问私有字段
在你的Spring配置类里,给ObjectMapper添加允许访问私有字段的配置:
@Bean public ObjectMapper objectMapper() { ObjectMapper objectMapper = new ObjectMapper(); // 让Jackson可以直接读取任意访问权限的字段 objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); return objectMapper; }
这样Jackson会跳过Getter检查,直接读取私有字段的值。
2. 给私有字段添加@JsonProperty注解
在MyHeader和MyBody的字段上加上@JsonProperty,明确告诉Jackson这个字段需要被序列化:
@Builder public class MyBody { @JsonProperty private String accountNumber; }
@Builder public class MyHeader { @JsonProperty private String username; @JsonProperty private String password; }
这个注解会让Jackson忽略Getter的存在,直接处理标注的字段。
3. 使用Lombok的@Jacksonized配合@Builder
如果你的Lombok版本在1.18.14及以上,可以用@Jacksonized注解配合@Builder,它会自动生成适配Jackson序列化的构建器逻辑,不需要额外的@Getter:
@Jacksonized @Builder public class MyBody { private String accountNumber; }
@Jacksonized @Builder public class MyHeader { private String username; private String password; }
这个注解会帮你配置Jackson识别Lombok生成的类,自动处理私有字段的序列化。
4. 将字段改为public(不推荐)
直接把accountNumber、username、password的修饰符改成public,Jackson可以直接读取字段值。但这种做法会破坏类的封装性,生产环境不建议使用。
内容的提问来源于stack exchange,提问作者Thiagarajan Ramanathan

