早上打开 IDE,又一个数据交互需求来了:前端要求返回的字段名用驼峰格式,数据库却是下划线命名;用户信息里的日期必须是"yyyy-MM-dd"格式;某些敏感字段在特定情况下不能返回......
这些场景是不是特别熟悉?如果你还在用大量的转换代码来处理这些问题,那就有点辛苦了。其实在 FastJSON 库里,一个小小的@JSONField
注解就能帮我们解决这些烦恼,让代码既简洁又优雅。今天,我们就一起深入了解这个强大的注解。
@JSONField 注解概述
@JSONField
是阿里巴巴 FastJSON 库提供的注解,主要用于控制 Java 对象与 JSON 之间的转换过程。通过它,我们可以自定义字段名、格式化日期、控制序列化/反序列化条件等,非常实用。
@JSONField 的核心属性详解
1. name 属性:自定义 JSON 字段名
有时候,我们的 Java 类字段名与期望的 JSON 字段名不一致,比如数据库使用下划线命名,而前端需要驼峰命名。这时就可以用name
属性来解决:
java
import com.alibaba.fastjson.annotation.JSONField;
import java.util.Date;
public class User {
@JSONField(name = "user_name")
private String userName;
@JSONField(name = "create_time")
private Date createTime;
// getter和setter省略
}
序列化后的 JSON:
json
{
"user_name": "张三",
"create_time": "2023-04-25 10:30:00"
}
反序列化时,FastJSON 会自动将 JSON 中的"user_name"映射到 Java 对象的 userName 字段,不论 Java 字段名是什么。
2. format 属性:日期时间格式化
处理日期时间是开发中的常见需求,format
属性让日期格式化变得超简单:
java
import com.alibaba.fastjson.annotation.JSONField;
import java.util.Date;
public class Order {
private Long id;
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
@JSONField(format = "yyyy-MM-dd")
private Date paymentDate;
// getter和setter省略
}
序列化效果:
json
{
"id": 1001,
"createTime": "2023-04-25 10:30:00",
"paymentDate": "2023-04-25"
}
反序列化时,如果 JSON 中的日期符合 format 指定的格式,FastJSON 会自动将字符串转换为 Date 对象:
java
import com.alibaba.fastjson.JSON;
String json = "{\"createTime\":\"2023-04-25 10:30:00\"}";
Order order = JSON.parseObject(json, Order.class);
// order.getCreateTime() 将是 Date 类型
3. serialize 和 deserialize 属性:控制字段的序列化/反序列化行为
有些字段可能只需要序列化但不需要反序列化,或者反过来,使用这两个属性就可以控制:
java
import com.alibaba.fastjson.annotation.JSONField;
public class UserInfo {
private Long id;
private String name;
// 序列化时包含该字段(返回给前端),反序列化时忽略(不接收前端传入)
@JSONField(serialize = true, deserialize = false)
private String sessionToken;
// 不序列化到JSON中(不返回给前端),但接收JSON中的该字段值(接收前端传入)
@JSONField(serialize = false, deserialize = true)
private String password;
// getter和setter省略
}
这个例子中,sessionToken
字段只会出现在生成的 JSON 中,而password
字段只会从 JSON 中读取但不会输出到 JSON,非常适合处理敏感信息。
4. ordinal 属性:控制字段顺序
如果你对 JSON 中字段的顺序有要求,可以使用ordinal
属性来控制:
java
import com.alibaba.fastjson.annotation.JSONField;
import java.math.BigDecimal;
import java.util.Date;
public class Product {
@JSONField(ordinal = 1)
private Long id;
@JSONField(ordinal = 2)
private String name;
@JSONField(ordinal = 3)
private BigDecimal price;
@JSONField(ordinal = 4)
private Date createTime;
// getter和setter省略
}
序列化后,字段会按照 ordinal 的值从小到大排序。注意,ordinal 属性仅影响序列化时的字段顺序,对反序列化没有影响。
5. serializeUsing 和 deserializeUsing 属性:自定义转换器
对于特殊类型的转换,我们可以使用自定义的序列化和反序列化处理器:
java
import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.ObjectSerializer;
import java.io.IOException;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.RoundingMode;
public class Product {
private Long id;
private String name;
// 使用自定义序列化器处理价格
@JSONField(serializeUsing = PriceSerializer.class)
private BigDecimal price;
// getter和setter省略
}
// 自定义序列化器 - 使用枚举单例模式避免反复创建实例
public enum PriceSerializer implements ObjectSerializer {
INSTANCE; // 单例模式,线程安全
@Override
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
BigDecimal price = (BigDecimal) object;
// 价格保留两位小数并转为字符串
String priceStr = price.setScale(2, RoundingMode.HALF_UP).toString();
serializer.write(priceStr);
}
}
在使用时,可以直接引用单例:
java
@JSONField(serializeUsing = PriceSerializer.INSTANCE)
private BigDecimal price;
对于反序列化,类似地可以使用deserializeUsing
:
java
import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.fastjson.parser.DefaultJSONParser;
import com.alibaba.fastjson.parser.JSONToken;
import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer;
import java.lang.reflect.Type;
import java.math.BigDecimal;
public class Product {
// 使用自定义反序列化器处理价格
@JSONField(deserializeUsing = PriceDeserializer.class)
private BigDecimal price;
// 其他字段和getter/setter省略
}
// 自定义反序列化器 - 同样使用枚举单例
public enum PriceDeserializer implements ObjectDeserializer {
INSTANCE;
@Override
public BigDecimal deserialize(DefaultJSONParser parser, Type type, Object fieldName) {
String priceStr = parser.lexer.stringVal();
// 处理空字符串、null或特殊格式
if (priceStr == null || priceStr.isEmpty()) {
return BigDecimal.ZERO;
}
try {
return new BigDecimal(priceStr);
} catch (Exception e) {
// 格式异常时返回默认值
return BigDecimal.ZERO;
}
}
@Override
public int getFastMatchToken() {
return JSONToken.LITERAL_STRING;
}
}
实际应用场景案例
场景一:API 接口数据转换
在实际项目中,我们经常需要处理前后端数据格式的差异,@JSONField
能大大简化这一过程:
java
import com.alibaba.fastjson.annotation.JSONField;
import io.swagger.annotations.ApiModelProperty; // 集成Swagger文档
import java.math.BigDecimal;
import java.util.Date;
public class OrderDTO {
private Long id;
// 同时配置Swagger文档与JSON序列化
@ApiModelProperty("订单编号")
@JSONField(name = "order_no")
private String orderNo;
@ApiModelProperty("创建时间")
@JSONField(name = "create_time", format = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
@ApiModelProperty("订单金额")
@JSONField(name = "total_amount")
private BigDecimal totalAmount;
@ApiModelProperty(value = "内部备注", hidden = true)
@JSONField(serialize = false)
private String remark; // 内部备注,不返回给前端
// getter和setter省略
}
场景二:处理枚举类型
对于枚举类型,我们可能希望 JSON 中存储的是枚举的名称或者自定义的值,而不是默认的序号。通过接口约束可以提高类型安全性:
java
import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.ObjectSerializer;
import java.io.IOException;
import java.lang.reflect.Type;
// 定义枚举描述接口,强制实现getDescription方法
public interface DescribableEnum {
String getDescription();
}
// 枚举类实现接口
public enum OrderStatus implements DescribableEnum {
PENDING("待付款"),
PAID("已付款"),
SHIPPED("已发货"),
DELIVERED("已签收"),
CANCELLED("已取消");
private String description;
OrderStatus(String description) {
this.description = description;
}
@Override
public String getDescription() {
return description;
}
}
public class Order {
private Long id;
// 使用自定义序列化器处理枚举
@JSONField(serializeUsing = EnumDescriptionSerializer.class)
private OrderStatus status;
// getter和setter省略
}
// 使用接口约束避免反射,提升类型安全 - 使用枚举单例
public enum EnumDescriptionSerializer implements ObjectSerializer {
INSTANCE;
@Override
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
if (object == null) {
serializer.writeNull();
return;
}
if (object instanceof DescribableEnum) {
// 直接调用接口方法,避免反射
serializer.write(((DescribableEnum)object).getDescription());
} else {
// 降级处理
serializer.write(((Enum<?>)object).name());
}
}
}
执行结果:
json
{
"id": 1001,
"status": "已付款"
}
场景三:处理敏感数据
对于用户的敏感信息,我们可以结合自定义序列化器来实现脱敏处理,并加强数据校验:
java
import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.ObjectSerializer;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.regex.Pattern;
public class Customer {
private Long id;
private String name;
@JSONField(serializeUsing = PhoneMaskSerializer.INSTANCE)
private String phone;
@JSONField(serializeUsing = IdCardMaskSerializer.INSTANCE)
private String idCard;
// getter和setter省略
}
// 手机号脱敏序列化器 - 枚举单例模式
public enum PhoneMaskSerializer implements ObjectSerializer {
INSTANCE;
// 手机号格式验证正则
private static final Pattern PHONE_PATTERN = Pattern.compile("^1[3-9]\\d{9}$");
@Override
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
String phone = (String) object;
if (phone == null) {
serializer.writeNull();
return;
}
// 手机号格式校验
if (!PHONE_PATTERN.matcher(phone).matches()) {
// 非标准手机号,返回固定格式脱敏结果
serializer.write("***********");
return;
}
// 中间4位用*替代
String maskedPhone = phone.substring(0, 3) + "****" + phone.substring(7);
serializer.write(maskedPhone);
}
}
// 身份证号脱敏序列化器 - 枚举单例模式
public enum IdCardMaskSerializer implements ObjectSerializer {
INSTANCE;
// 身份证号格式验证正则(支持15位和18位)
private static final Pattern ID_CARD_PATTERN = Pattern.compile("(^\\d{15}$)|(^\\d{17}[0-9Xx]$)");
@Override
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
String idCard = (String) object;
if (idCard == null) {
serializer.writeNull();
return;
}
// 身份证号格式校验
if (!ID_CARD_PATTERN.matcher(idCard).matches()) {
// 非标准身份证号,返回固定格式脱敏结果
serializer.write("****************");
return;
}
// 保留前4位和后4位,中间用*替代
String maskedIdCard = idCard.substring(0, 4) + "**********" + idCard.substring(idCard.length() - 4);
serializer.write(maskedIdCard);
}
}
效果:
json
{
"id": 1001,
"name": "张三",
"phone": "138****8888",
"idCard": "3101**********1234"
}
场景四:处理循环引用
在实际开发中,对象之间的双向关联很常见,但这会导致序列化时的循环引用问题:
java
import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.fastjson.annotation.JSONType;
import java.util.List;
// 部门与员工的双向关联
public class Department {
private Long id;
private String name;
private List<Employee> employees;
// getter和setter省略
}
public class Employee {
private Long id;
private String name;
// 通过serialize=false截断循环引用链
@JSONField(serialize = false)
private Department department;
// getter和setter省略
}
// 使用类级注解处理更复杂的循环引用场景
@JSONType(ignores = {"parent"}) // 类级别统一配置,忽略parent字段
public class TreeNode {
private Long id;
private String name;
private TreeNode parent; // 将被忽略序列化
private List<TreeNode> children; // 子节点集合
// getter和setter省略
}
这样设计可以有效避免序列化时的栈溢出错误。通过在关联关系的一端设置serialize=false
或使用@JSONType
注解的ignores
属性,我们能保证数据结构是单向的,从而避免循环引用问题。
对于更复杂的多层嵌套循环引用,还可以结合 FastJSON 的全局配置:
java
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
// 使用DisableCircularReferenceDetect特性(谨慎使用,可能导致栈溢出)
String json = JSON.toJSONString(department,
SerializerFeature.DisableCircularReferenceDetect);
场景五:批量配置与统一转换
当一个类中有多个字段需要类似的配置时,可以使用@JSONType
进行批量配置:
java
import com.alibaba.fastjson.annotation.JSONType;
import java.util.Date;
// 批量配置字段名映射,避免重复注解
@JSONType(naming = PropertyNamingStrategy.SnakeCase) // 驼峰转下划线命名
public class OrderDTO {
private Long id; // 转为 "id"
private String orderNo; // 转为 "order_no"
private Date createTime; // 转为 "create_time"
private BigDecimal totalAmount; // 转为 "total_amount"
// 更多字段...
}
// 批量忽略指定字段
@JSONType(ignores = {"password", "salt", "securityQuestion"})
public class UserDTO {
private Long id;
private String username;
private String password; // 将被忽略
private String salt; // 将被忽略
private String securityQuestion; // 将被忽略
// 更多字段...
}
@JSONField 与其他 JSON 库的详细对比
FastJSON 的@JSONField
并不是唯一的选择,下面是与其他主流 JSON 库功能对比:
功能 | FastJSON(@JSONField) | Jackson | Gson | 适用场景推荐 |
---|---|---|---|---|
字段重命名 | name 属性 | @JsonProperty(value="xx") | @SerializedName("xx") | 需兼容前后端命名规范差异时,三者都可 |
日期格式化 | format 属性 | @JsonFormat(pattern="xx") | 需自定义 TypeAdapter | 日期格式化需求,FastJSON/Jackson 更简便 |
控制序列化/反序列化 | serialize/deserialize 属性 | @JsonIgnore,@JsonProperty(access=...) | @Expose(serialize=..,deserialize=..) | 处理敏感字段时,FastJSON 语义更清晰 |
字段排序 | ordinal 属性 | @JsonPropertyOrder | 不支持,按声明顺序 | 严格字段顺序要求场景选择 FastJSON/Jackson |
自定义转换器 | serializeUsing/deserializeUsing 属性 | @JsonSerialize/@JsonDeserialize | TypeAdapter+@JsonAdapter | 复杂类型转换场景,Jackson 支持最完善 |
空值处理 | SerializerFeature.WriteMapNullValue | @JsonInclude(Include.ALWAYS) | 默认包含 null | 严格控制 null 值输出时,Jackson 更灵活 |
安全性注意事项 | 1.2.68 前存在 AutoType 漏洞 | 强类型设计,安全性较高 | 默认不支持任意类型反序列化 | 高安全要求场景建议使用 Jackson/Gson |
⚠️ 注意:FastJSON 在 1.2.68 以前版本存在 AutoType 安全漏洞,应升级至最新版本(可通过mvn dependency:tree
或 Gradle 依赖检查确认版本)。Jackson 默认采用严格匹配字段名策略,不支持驼峰-下划线自动转换(需开启 PropertyNamingStrategy)。
选择时可以考虑项目规模、团队熟悉度和性能需求。FastJSON 操作简便但需关注安全配置;Jackson 功能全面但配置较多;Gson 轻量级但某些高级功能需额外开发。
@JSONField 使用时的注意事项
1. 循环引用处理
在对象间存在双向关联时,必须合理使用serialize=false
来截断循环:
java
// 错误示例:双向引用未截断,将导致栈溢出
class Parent {
private List<Child> children;
}
class Child {
private Parent parent; // 会导致循环引用
}
// 正确示例:截断循环
class Parent {
private List<Child> children;
}
class Child {
@JSONField(serialize = false)
private Parent parent; // 序列化时忽略此字段
}
2. 日期格式统一
在一个项目中,保持日期格式的一致性,可以通过全局配置来统一:
java
// 在应用启动时设置全局默认日期格式(线程安全考虑应在启动时一次性配置)
JSON.DEFFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
注意:JSON.DEFFAULT_DATE_FORMAT
是静态变量,为确保线程安全,建议在应用启动时一次性配置完成,避免运行时修改。
3. 环境差异化配置
不同环境可能需要不同的序列化策略,例如开发环境可能需要更详细的信息:
java
// 非生产环境才序列化调试信息字段
@JSONField(serialize = !AppConfig.isProduction())
private String debugInfo;
4. 序列化性能优化
自定义序列化器在高并发场景下会引入额外开销。通过测试,使用自定义序列化器可能导致 10%-20%的性能损耗,可采用以下方式优化:
java
// 1. 使用枚举单例模式,避免频繁创建对象
@JSONField(serializeUsing = PhoneMaskSerializer.INSTANCE)
private String phone;
// 2. 使用SerializeFilter而非自定义序列化器
ValueFilter phoneFilter = (obj, name, value) -> {
if ("phone".equals(name) && value instanceof String) {
// 处理手机号逻辑
}
return value;
};
JSON.toJSONString(customer, phoneFilter);
// 3. 类级别配置,减少字段级反射
@JSONType(serialzeFilters = {MyGlobalFilter.class})
public class Customer {
// ...
}
// 4. 对基础类型优先使用内置特性
@JSONField(serialzeFeatures = SerializerFeature.WriteBigDecimalAsPlain)
private BigDecimal price; // 使用内置特性代替自定义序列化器
高级应用技巧
1. 框架集成方案
与 Spring Boot 集成
在 Spring Boot 项目中集成 FastJSON 作为默认 JSON 处理器:
java
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FastJsonConfiguration {
@Bean
public HttpMessageConverters fastJsonHttpMessageConverters() {
// 创建FastJSON消息转换器
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
// 创建配置
FastJsonConfig config = new FastJsonConfig();
// 配置全局日期格式和null值处理,解决前后端日期格式不一致、null值字段丢失等问题
config.setDateFormat("yyyy-MM-dd HH:mm:ss");
config.setSerializerFeatures(
SerializerFeature.WriteMapNullValue, // 输出null值字段(默认忽略)
SerializerFeature.WriteNullStringAsEmpty // null字符串输出为空字符串
);
converter.setFastJsonConfig(config);
return new HttpMessageConverters(converter);
}
}
与 Spring MVC 集成
在传统 Spring MVC 项目中使用 FastJSON:
java
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.List;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
FastJsonConfig config = new FastJsonConfig();
// 配置...
converter.setFastJsonConfig(config);
converters.add(0, converter); // 添加至首位,优先使用
}
}
与 Swagger 集成
在 API 文档中结合使用 FastJSON 和 Swagger 注解:
java
import com.alibaba.fastjson.annotation.JSONField;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ApiModel("用户信息")
public class UserDTO {
@ApiModelProperty("用户ID")
private Long id;
@ApiModelProperty("用户名")
private String username;
@ApiModelProperty("手机号")
@JSONField(serializeUsing = PhoneMaskSerializer.INSTANCE)
private String phone;
@ApiModelProperty(value = "密码", hidden = true)
@JSONField(serialize = false, deserialize = true)
private String password;
}
2. 安全与性能调优
安全配置要点
FastJSON 有较多安全配置需关注:
java
// 全局安全配置,限制可反序列化的类
ParserConfig.getGlobalInstance().addAccept("com.yourcompany.model.");
// 禁用AutoType,防止远程代码执行漏洞
ParserConfig.getGlobalInstance().setAutoTypeSupport(false);
// 检查依赖版本(在pom.xml中确保)
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version> <!-- 使用最新安全版本 -->
</dependency>
升级 FastJSON 库时,可通过以下命令检查当前版本:
bash
# Maven项目
mvn dependency:tree | grep fastjson
# Gradle项目
./gradlew dependencies | grep fastjson
性能调优策略
针对不同场景的性能调优:
java
// 场景1:简单对象频繁序列化,使用SerializerFeature组合
JSON.toJSONString(object,
SerializerFeature.DisableCircularReferenceDetect, // 禁用循环检测提升性能
SerializerFeature.WriteDateUseDateFormat); // 使用默认日期格式而非ISO8601
// 场景2:大批量序列化,使用字节数组提升性能
byte[] jsonBytes = JSON.toJSONBytes(object);
// 场景3:复杂条件过滤,使用过滤器
PropertyPreFilter filter = new SimplePropertyPreFilter(User.class, "id", "name");
String json = JSON.toJSONString(users, filter);
// 场景4:频繁访问JSON,预编译JSONPath提高查询性能
JSONPath path = JSONPath.compile("$.name");
String name = path.eval(jsonObject);
不同优化策略的适用场景:
SerializerFeature
:适合简单对象的高频序列化- 自定义序列化器:适合需精确控制输出格式的场景
- 过滤器:适合根据运行时条件动态过滤字段
- 类级别注解:适合批量配置相同转换规则
3. 工程化应用规范
与 Lombok 配合使用
FastJSON 与 Lombok 搭配能大大减少样板代码:
java
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;
import java.util.Date;
@Data // 自动生成getter/setter/toString等
public class UserDTO {
private Long id;
@JSONField(name = "user_name")
private String userName;
@JSONField(format = "yyyy-MM-dd")
private Date birthday;
}
DTO 层设计模式
在多层架构中统一使用@JSONField:
java
// 仅在DTO层使用@JSONField,保持实体层的纯净
@Data
public class UserDTO {
// DTO层处理JSON转换细节
@JSONField(name = "user_id")
private Long id;
// 使用自定义序列化器处理敏感数据
@JSONField(serializeUsing = PhoneMaskSerializer.INSTANCE)
private String phone;
// 转换方法(从实体到DTO)
public static UserDTO fromEntity(User user) {
UserDTO dto = new UserDTO();
dto.setId(user.getId());
dto.setPhone(user.getPhone());
return dto;
}
}
全局过滤器应用
利用过滤器实现全局字段控制:
java
// 根据当前用户角色决定是否输出敏感字段
SimplePropertyPreFilter filter = new SimplePropertyPreFilter();
// 动态配置过滤规则
if (!currentUser.isAdmin()) {
// 非管理员用户过滤敏感字段
filter.getExcludes().add("idCard");
filter.getExcludes().add("bankAccount");
}
// 应用过滤器
String json = JSON.toJSONString(user, filter);
总结
下面用表格总结一下@JSONField 的核心功能:
属性名 | 功能描述 | 适用场景 | 影响反序列化? |
---|---|---|---|
name | 自定义 JSON 字段名 | 解决 Java 字段名与 JSON 字段名不一致的问题 | ✓ 影响 |
format | 日期时间格式化 | 自定义日期、时间的输出格式 | ✓ 影响 |
serialize | 控制字段是否序列化 | 隐藏敏感字段不输出到 JSON | ✗ 不影响 |
deserialize | 控制字段是否反序列化 | 阻止某些字段从 JSON 中读取值 | ✓ 影响 |
ordinal | 控制字段序列化顺序 | 需要固定 JSON 字段顺序的场景 | ✗ 不影响 |
serializeUsing | 自定义序列化处理器 | 复杂类型转换、数据脱敏等场景 | ✗ 不影响 |
deserializeUsing | 自定义反序列化处理器 | 特殊格式数据的解析场景 | ✓ 影响 |