1. 为什么需要字段别名在实际开发中我们经常遇到这样的场景后端定义的Java对象字段名跟前端或第三方系统要求的JSON字段名不一致。比如你的Java类里有个字段叫userName但接口文档要求返回username或者你对接的支付平台要求传参order_id但你的系统里字段叫orderId。这时候如果直接序列化字段名对不上系统就会报错。我去年做电商项目时就踩过这个坑。对接物流系统时对方要求的字段全是下划线命名法如delivery_time而我们系统内部用的是驼峰命名deliveryTime。当时手动写了一大堆转换代码后来才发现fastjson的JSONField注解能一键解决这个问题。2. JSONField注解基础用法2.1 最简单的别名设置先看个最简单的例子。假设我们有个用户类需要把name字段在JSON中显示为usernamepublic class User { JSONField(name username) private String name; // 构造方法、getter/setter省略 }当用JSON.toJSONString()序列化时输出会是{username:张三}2.2 同时处理序列化和反序列化JSONField的妙处在于它是双向生效的。还是上面的例子如果我们收到一个JSON{username:李四}用JSON.parseObject()反序列化时也能正确映射到Java对象的name字段User user JSON.parseObject(jsonStr, User.class); System.out.println(user.getName()); // 输出李四3. 高级用法实战3.1 处理复杂嵌套对象实际项目中我们经常要处理嵌套对象。比如订单信息里包含用户信息public class Order { JSONField(name order_id) private String orderId; JSONField(name user_info) private User user; } public class User { JSONField(name user_name) private String name; }序列化后会变成{ order_id:123456, user_info:{ user_name:王五 } }3.2 配合其他注解参数JSONField还有其他实用参数format日期格式化serialize/deserialize控制是否参与序列化/反序列化比如处理日期字段public class Event { JSONField(name event_time, format yyyy-MM-dd HH:mm:ss) private Date time; }4. 实际项目中的避坑指南4.1 版本兼容性问题fastjson不同版本对注解的支持有差异。我遇到过1.2.36版本下format参数失效的问题。建议使用较新稳定版如1.2.83在pom.xml固定版本号dependency groupIdcom.alibaba/groupId artifactIdfastjson/artifactId version1.2.83/version /dependency4.2 与lombok的配合使用如果项目用了lombok要注意注解顺序。正确的写法是Data public class Product { JSONField(name product_name) private String name; }如果把Data和JSONField写反了可能会导致注解不生效。4.3 处理null值默认情况下fastjson会忽略null值字段。如果需要显示null值可以全局配置JSON.toJSONString(obj, SerializerFeature.WriteMapNullValue);或者在特定字段上配置JSONField(serialzeFeatures SerializerFeature.WriteMapNullValue) private String address;5. 性能优化建议在大流量场景下fastjson的序列化性能很重要。经过实测我发现避免在循环内部重复创建JSONField注解对象对于不变的配置使用static final修饰private static final SerializerFeature[] features { SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullStringAsEmpty };考虑使用JSONType注解在类级别统一配置JSONType(includes {name,age}, ignores {password}) public class User { // 字段定义 }6. 与其他JSON库的对比虽然fastjson的注解功能很强大但在某些场景下可能需要考虑其他方案Jackson方案JsonProperty(user_name) private String name;Gson方案SerializedName(user_name) private String name;选择建议如果项目已经用了fastjson直接用JSONField最方便新项目可以考虑Jackson生态更完善Android开发推荐Gson7. 最佳实践总结经过多个项目的实战我总结出这些经验团队统一命名规范减少别名使用在DTO层集中处理字段映射不要污染领域模型编写单元测试验证序列化结果接口文档要同时注明Java字段名和JSON字段名最后分享一个真实案例我们系统对接银行接口时对方要求的字段名全是大写字母加下划线如ACCOUNT_NO。通过在DTO层统一使用JSONField既保持了内部代码规范又完美满足了接口要求。整个对接过程只用了半天就完成了联调。
fastjson字段别名实战:@JSONField注解的灵活运用
1. 为什么需要字段别名在实际开发中我们经常遇到这样的场景后端定义的Java对象字段名跟前端或第三方系统要求的JSON字段名不一致。比如你的Java类里有个字段叫userName但接口文档要求返回username或者你对接的支付平台要求传参order_id但你的系统里字段叫orderId。这时候如果直接序列化字段名对不上系统就会报错。我去年做电商项目时就踩过这个坑。对接物流系统时对方要求的字段全是下划线命名法如delivery_time而我们系统内部用的是驼峰命名deliveryTime。当时手动写了一大堆转换代码后来才发现fastjson的JSONField注解能一键解决这个问题。2. JSONField注解基础用法2.1 最简单的别名设置先看个最简单的例子。假设我们有个用户类需要把name字段在JSON中显示为usernamepublic class User { JSONField(name username) private String name; // 构造方法、getter/setter省略 }当用JSON.toJSONString()序列化时输出会是{username:张三}2.2 同时处理序列化和反序列化JSONField的妙处在于它是双向生效的。还是上面的例子如果我们收到一个JSON{username:李四}用JSON.parseObject()反序列化时也能正确映射到Java对象的name字段User user JSON.parseObject(jsonStr, User.class); System.out.println(user.getName()); // 输出李四3. 高级用法实战3.1 处理复杂嵌套对象实际项目中我们经常要处理嵌套对象。比如订单信息里包含用户信息public class Order { JSONField(name order_id) private String orderId; JSONField(name user_info) private User user; } public class User { JSONField(name user_name) private String name; }序列化后会变成{ order_id:123456, user_info:{ user_name:王五 } }3.2 配合其他注解参数JSONField还有其他实用参数format日期格式化serialize/deserialize控制是否参与序列化/反序列化比如处理日期字段public class Event { JSONField(name event_time, format yyyy-MM-dd HH:mm:ss) private Date time; }4. 实际项目中的避坑指南4.1 版本兼容性问题fastjson不同版本对注解的支持有差异。我遇到过1.2.36版本下format参数失效的问题。建议使用较新稳定版如1.2.83在pom.xml固定版本号dependency groupIdcom.alibaba/groupId artifactIdfastjson/artifactId version1.2.83/version /dependency4.2 与lombok的配合使用如果项目用了lombok要注意注解顺序。正确的写法是Data public class Product { JSONField(name product_name) private String name; }如果把Data和JSONField写反了可能会导致注解不生效。4.3 处理null值默认情况下fastjson会忽略null值字段。如果需要显示null值可以全局配置JSON.toJSONString(obj, SerializerFeature.WriteMapNullValue);或者在特定字段上配置JSONField(serialzeFeatures SerializerFeature.WriteMapNullValue) private String address;5. 性能优化建议在大流量场景下fastjson的序列化性能很重要。经过实测我发现避免在循环内部重复创建JSONField注解对象对于不变的配置使用static final修饰private static final SerializerFeature[] features { SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullStringAsEmpty };考虑使用JSONType注解在类级别统一配置JSONType(includes {name,age}, ignores {password}) public class User { // 字段定义 }6. 与其他JSON库的对比虽然fastjson的注解功能很强大但在某些场景下可能需要考虑其他方案Jackson方案JsonProperty(user_name) private String name;Gson方案SerializedName(user_name) private String name;选择建议如果项目已经用了fastjson直接用JSONField最方便新项目可以考虑Jackson生态更完善Android开发推荐Gson7. 最佳实践总结经过多个项目的实战我总结出这些经验团队统一命名规范减少别名使用在DTO层集中处理字段映射不要污染领域模型编写单元测试验证序列化结果接口文档要同时注明Java字段名和JSON字段名最后分享一个真实案例我们系统对接银行接口时对方要求的字段名全是大写字母加下划线如ACCOUNT_NO。通过在DTO层统一使用JSONField既保持了内部代码规范又完美满足了接口要求。整个对接过程只用了半天就完成了联调。