Java 序列化工具:@JSONField 注解实战解析与应用技巧

早上打开 IDE,又一个数据交互需求来了:前端要求返回的字段名用驼峰格式,数据库却是下划线命名;用户信息里的日期必须是"yyyy-MM-dd"格式;某些敏感字段在特定情况下不能返回......

这些场景是不是特别熟悉?如果你还在用大量的转换代码来处理这些问题,那就有点辛苦了。其实在 FastJSON 库里,一个小小的@JSONField注解就能帮我们解决这些烦恼,让代码既简洁又优雅。今天,我们就一起深入了解这个强大的注解。

@JSONField 注解概述

@JSONField是阿里巴巴 FastJSON 库提供的注解,主要用于控制 Java 对象与 JSON 之间的转换过程。通过它,我们可以自定义字段名、格式化日期、控制序列化/反序列化条件等,非常实用。

graph LR A[Java对象] --序列化--> B{FastJSON引擎} B --"@JSONField控制"--> C[JSON字符串] C --反序列化--> B B --"@JSONField控制"--> A

@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)。

graph TB A[Java对象与JSON转换] --> B[FastJSON] A --> C[Jackson] A --> D[Gson] B --> E["@JSONField - 单注解多功能"] C --> F[多注解分工明确] D --> G[注解+适配器模式]

选择时可以考虑项目规模、团队熟悉度和性能需求。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 自定义反序列化处理器 特殊格式数据的解析场景 ✓ 影响
相关推荐
是发财不是旺财12 分钟前
跟着deepseek学golang--认识golang
开发语言·后端·golang
我的golang之路果然有问题12 分钟前
快速上手GO的net/http包,个人学习笔记
笔记·后端·学习·http·golang·go·net
Apifox.14 分钟前
Apifox 4月更新|Apifox在线文档支持LLMs.txt、评论支持使用@提及成员、支持为团队配置「IP 允许访问名单」
前端·人工智能·后端·ai·ai编程
界面开发小八哥1 小时前
Java开发工具IntelliJ IDEA v2025.1——全面支持Java 24、整合AI
java·ide·人工智能·intellij-idea·idea
BXCQ_xuan1 小时前
基于Node.js的健身会员管理系统的后端开发实践
后端·mysql·node.js
普兰店拉马努金1 小时前
【高中数学/古典概率】4红2黑六选二,求取出两次都是红球的概率
java·概率
智商低情商凑1 小时前
CAS(Compare And Swap)
java·jvm·面试
yangmf20401 小时前
使用 Logstash 迁移 MongoDB 数据到 Easysearch
java·elasticsearch·搜索引擎
Tiger_shl1 小时前
【Python语言基础】24、并发编程
java·数据库·python
拉满buff搞代码1 小时前
搞定 PDF“膨胀”难题:Python + Java 的超实用压缩秘籍
后端