嘿,各位技术探险家! 欢迎来到今天的博客,今天我们要聊一个既基础又充满戏剧性的问题:为什么我的 location
字段没有 getter
方法就没法返回给前端?这是一个发生在 Java 和 JSON 序列化世界中的小小“悬案”,让我们戴上侦探帽,一起揭开它的神秘面纱吧!
想象一下,你是一个勤奋的后端开发者,正在为前端小伙伴打造一个炫酷的商品列表接口。你的 ProductListDto
类里有一个 location
字段,代表商品的产地。你信心满满地在构造函数里赋值:
public ProductListDto(ProductWithShareDto dto) {
this.location = dto.getLocation(); // 嘿,我把产地放进去了!
// 其他字段...
}
你启动程序,信心十足地返回 BaseResult
,期待前端收到完美的 JSON 数据。然而,当你打开浏览器查看响应时,震惊了:location
竟然不见了! JSON 里干干净净,像是被魔法擦掉了一样。前端小伙伴一脸茫然地看着你:“产地呢?说好的 ‘日本’ 呢?” 你挠挠头,嘀咕道:“我明明赋值了呀,怎么回事?难道代码闹鬼了?”
别急,这不是灵异事件,而是 Java 和 JSON 序列化的“潜规则”在作怪!让我们一步步解开这个谜团吧。
在 Java 的世界里,字段默认是害羞的小家伙,它们喜欢藏在 private
的小房间里,比如:
@ApiModelProperty("产地")
private String location;
这些私有字段对外界来说是隐形的,Spring 和 Jackson(JSON 序列化的幕后英雄)也看不到它们。那么,Jackson 是怎么把 location
变成 JSON 的呢?答案是:它需要一个“通行证”——getter
方法!✨
Jackson 的默认行为是这样的:它会扫描你的类,寻找所有 public
的 getter
方法。比如:
public String getLocation() {
return location;
}
有了这个 getLocation()
,Jackson 就像拿到了一把钥匙,能打开 location
的房门,把里面的值(比如“日本”)拿出来,塞进 JSON 里。如果没有这个方法,Jackson 会无奈地耸肩:“抱歉,我进不去这个房间,location
对我来说不存在!” 于是,你的 JSON 里就少了一个字段。
让我们做个小实验:
场景 1:没有 getter
private String location;
public ProductListDto(ProductWithShareDto dto) {
this.location = dto.getLocation();
}
返回的 JSON:
{
"id": 144,
"name": "诺薇雅 精纯蜜粉饼 12g",
// location 呢?没了!
}
场景 2:加上 getter
private String location;
public ProductListDto(ProductWithShareDto dto) {
this.location = dto.getLocation();
}
public String getLocation() {
return location;
}
返回的 JSON:
{
"id": 144,
"name": "诺薇雅 精纯蜜粉饼 12g",
"location": "日本" // 哇,出现了!
}
是不是很神奇?getter
就像一个开关,决定了 location
能不能“出镜”!
那 setter
呢?比如:
public void setLocation(String location) {
this.location = location;
}
它在序列化(Java → JSON)中其实是个“隐形人”。为什么?因为序列化只需要读取数据(getter
),而不需要修改数据(setter
)。在你的 @GetMapping("admin/list")
接口中,ProductListDto
是输出给前端的,Jackson 只关心如何把对象变成 JSON,所以 setter
可有可无。
但别小看 setter
!如果你的接口需要接收前端传来的 JSON(比如 POST 请求),把它反序列化成 ProductListDto
,那 setter
就成了主角。没有它,Jackson 会抱怨:“我没法把 JSON 的 location
塞进对象里呀!”
你可能会问:“序列化的代码到底在哪里?我怎么没看到?” 哈哈,这是个狡猾的小秘密!序列化其实藏在 Spring 的幕后,由 MappingJackson2HttpMessageConverter
和 Jackson 的 ObjectMapper
联手完成。当你返回 BaseResult
时,Spring 会悄悄调用:
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(yourObject); // 魔法发生在这里!
这段代码不在你的业务逻辑里,而是 Spring MVC 的响应处理流程的一部分。你可以想象,Jackson 像个忙碌的邮递员,挨个敲开 getter
的门,把字段装进 JSON 包裹里寄给前端。
“非要写 getter
吗?有没有偷懒的办法?” 当然有,但小心副作用哦!
把字段变 public
:
public String location; // 直接公开
location
。调整 Jackson 配置:
application.properties
加一句:spring.jackson.visibility.field=ANY
private
的。还是老老实实写 getter
吧,既安全又优雅,何乐而不为呢?
经过这场侦探之旅,我们终于明白了:location
字段没有 getter
方法,就没法返回给前端,因为 Jackson 靠 getter
来“看”字段。没有它,location
就像藏在箱子里的宝藏,前端永远看不到。加上 getter
,它就闪亮登场,完美呈现在 JSON 里!
所以,下次写 DTO 时,记得给每个想展示的字段配上 getter
,就像给它们发一张“上台表演”的门票。至于 setter
,留给需要接收数据的场景吧。让我们用代码点亮前端的世界吧!
希望这篇博客让你对 getter
和 setter
的影响有了新的认识!是不是觉得序列化的世界既有趣又有逻辑?如果还有什么疑问,或者想聊聊其他技术“悬案”,随时在评论区找我哦!我会带着更多表情和趣味故事回来陪伴你! 这次探险到此结束,我们下次再见啦~
希望这篇博客符合你的期待!