如何优雅地使用@JsonProperty实现对象字段重命名及小写字段返回?
问题
我有一个接口,逻辑是先调用第三方API获取数据,再返回JSON给前端展示。
第三方API的响应示例:
{ "ShipperCode": "SF", "SendProvince": "", "SendCity": "", "SendArea": "", "SendAddress": "", "ReceiveProvince": "", "ReceiveCity": "", "ReceiveArea": "", "ReceiveAddress": "", "DeliveryTime": "", "DeliveryDate": "", "Hour": "", "PredictPath": "" }
我已经定义了PredictTimeDO对象来接收第三方API的返回结果:
public class PredictTimeDO { @JsonProperty("ShipperCode") private String shipperCode; @JsonProperty("SendProvince") private String sendProvince; @JsonProperty("SendCity") private String sendCity; @JsonProperty("SendArea") private String sendArea; @JsonProperty("SendAddress") private String sendAddress; @JsonProperty("ReceiveProvince") private String receiveProvince; @JsonProperty("ReceiveCity") private String receiveCity; @JsonProperty("ReceiveArea") private String receiveArea; @JsonProperty("ReceiveAddress") private String receiveAddress; @JsonProperty("DeliveryTime") private String deliveryTime; @JsonProperty("DeliveryDate") private String deliveryDate; @JsonProperty("Hour") private String hour; @JsonProperty("PredictPath") private String predictPath; }
现在需要将该对象转换为小写字段名的JSON返回给前端,示例如下:
{ "shipperCode": "", "sendProvince": "", "sendCity": "", "sendArea": "", "sendAddress": "", "receiveProvince": "", "receiveCity": "", "receiveArea": "", "receiveAddress": "", "deliveryTime": "", "deliveryDate": "", "hour": "", "predictPath": "" }
我知道一种方法是定义PredictTimeDTO对象并手动复制PredictTimeDO的属性值,但想知道有没有更优雅的解决方式?
优雅解决方案
1. 修改DO类注解,用@JsonAlias替代@JsonProperty
这种方式无需额外创建DTO,直接调整DO类的反序列化注解即可:
@JsonAlias用于指定反序列化时可以识别的别名(对应第三方API的大驼峰字段)- 类属性本身保持小驼峰命名,序列化时直接输出小驼峰字段名,完美匹配前端需求
修改后的PredictTimeDO代码:
public class PredictTimeDO { @JsonAlias("ShipperCode") private String shipperCode; @JsonAlias("SendProvince") private String sendProvince; @JsonAlias("SendCity") private String sendCity; @JsonAlias("SendArea") private String sendArea; @JsonAlias("SendAddress") private String sendAddress; @JsonAlias("ReceiveProvince") private String receiveProvince; @JsonAlias("ReceiveCity") private String receiveCity; @JsonAlias("ReceiveArea") private String receiveArea; @JsonAlias("ReceiveAddress") private String receiveAddress; @JsonAlias("DeliveryTime") private String deliveryTime; @JsonAlias("DeliveryDate") private String deliveryDate; @JsonAlias("Hour") private String hour; @JsonAlias("PredictPath") private String predictPath; // 需添加getter/setter方法 }
2. 使用Bean映射工具自动完成DO到DTO的转换
如果不想修改现有DO类的注解,可以用MapStruct、ModelMapper这类工具自动处理属性复制,避免手动编写重复的get/set代码:
以MapStruct为例:
- 引入MapStruct依赖(根据项目构建工具调整,比如Maven/Gradle)
- 定义映射接口:
@Mapper(componentModel = "spring") public interface PredictTimeMapper { PredictTimeMapper INSTANCE = Mappers.getMapper(PredictTimeMapper.class); PredictTimeDTO doToDto(PredictTimeDO predictTimeDO); }
- 业务代码中直接调用:
PredictTimeDO predictTimeDO = thirdPartyApiClient.getData(); PredictTimeDTO dto = PredictTimeMapper.INSTANCE.doToDto(predictTimeDO); // 直接返回dto即可
3. 临时配置ObjectMapper的序列化规则
如果仅在当前接口需要小驼峰输出,其他场景仍需保留原注解的序列化行为,可以临时调整ObjectMapper的配置:
@RequestMapping("/predict-time") public String getPredictTime() throws JsonProcessingException { PredictTimeDO predictTimeDO = thirdPartyApiClient.getPredictTime(); ObjectMapper mapper = new ObjectMapper(); // 禁用注解对序列化的影响,直接使用字段的原始小驼峰名称 mapper.configure(MapperFeature.USE_ANNOTATIONS, false); // 确保命名策略为小驼峰(可选,因为字段本身已经是小驼峰) mapper.setPropertyNamingStrategy(PropertyNamingStrategy.LOWER_CAMEL_CASE); return mapper.writeValueAsString(predictTimeDO); }
注意:这种方式会忽略DO类上的所有Jackson注解,使用时需确认无其他注解依赖。
内容的提问来源于stack exchange,提问作者Holinc
相关产品推荐
相关产品推荐

