Java实用注解篇: @JSONField

前言

在 Java 开发中,进行对象与 JSON 的相互转换是一项常见操作,尤其在前后端分离的架构中显得尤为重要。Fastjson 作为阿里巴巴开源的 JSON 处理框架,因其高性能和强大功能而被广泛使用。@JSONField 是 Fastjson 提供的一个注解,用于精细控制 Java Bean 字段在序列化(Java 对象转 JSON)与反序列化(JSON 转 Java 对象)时的行为。


为什么需要 @JSONField?它解决了哪些痛点?

在日常开发中,我们经常会遇到以下几个痛点:

  • Java 字段名与前端字段不一致 :前端使用的是 user_name,而 Java 中是 username,映射困难。

  • 时间格式不统一:JSON 默认的时间格式与系统或业务需求不同,需要手动格式化。

  • 字段冗余或安全隐患 :某些字段如 passwordtoken 不能被序列化,但默认会输出。

  • 后端字段更新但兼容老版本前端字段名:需要兼容多个字段名进行反序列化。

@JSONField 注解可以精准控制每一个字段的序列化和反序列化行为,从而有效解决上述问题,提高开发效率并降低出错概率。


一、@JSONField 注解简介

@JSONField 注解是 Fastjson 提供的元注解,位于 com.alibaba.fastjson.annotation.JSONField 包中。它允许开发者在字段或方法上配置特定的序列化/反序列化规则,从而达到灵活控制 JSON 输出和输入的目的。


二、常用属性说明

属性名 类型 说明
name String 指定字段在 JSON 中的名称
format String 指定日期格式,例如 "yyyy-MM-dd HH:mm:ss"
serialize boolean 是否参与序列化,默认 true
deserialize boolean 是否参与反序列化,默认 true
ordinal int 字段排序优先级,值越小越靠前
defaultValue String 反序列化时的默认值
alternateNames String[] 支持反序列化时的多个字段名

三、基本使用示例

1. 重命名字段

java 复制代码
public class User {
    @JSONField(name = "user_name")
    private String username;

    // Getter & Setter
}

输出的 JSON:

java 复制代码
{
  "user_name": "jack"
}

2. 格式化日期字段

java 复制代码
public class Event {
    @JSONField(format = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;
}

3. 控制字段参与序列化/反序列化

java 复制代码
public class Login {
    @JSONField(serialize = false)
    private String password;

    @JSONField(deserialize = false)
    private String token;
}

4. 使用别名反序列化

java 复制代码
public class Product {
    @JSONField(alternateNames = {"productId", "id"})
    private Long pid;
}

无论 JSON 中是 productId 还是 id,都能正确反序列化为 pid 字段。


四、进阶技巧:搭配方法使用

除了作用在字段上,@JSONField 还可以作用在方法(尤其是 getter/setter)上,控制方法参与序列化与反序列化的行为:

java 复制代码
public class Order {
    private String status;

    @JSONField(name = "order_status")
    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }
}

五、完整代码示例

我们通过一个综合示例类来演示多个 @JSONField 功能的组合使用:

java 复制代码
// JSONFieldDemo.java
package com.example.fastjsondemo;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.annotation.JSONField;

import java.util.Date;

public class JSONFieldDemo {

    static class User {
        @JSONField(name = "user_name")
        private String username;

        @JSONField(serialize = false)
        private String password;

        @JSONField(format = "yyyy-MM-dd HH:mm:ss")
        private Date createdAt;

        public User(String username, String password, Date createdAt) {
            this.username = username;
            this.password = password;
            this.createdAt = createdAt;
        }

        public String getUsername() { return username; }
        public void setUsername(String username) { this.username = username; }

        public String getPassword() { return password; }
        public void setPassword(String password) { this.password = password; }

        public Date getCreatedAt() { return createdAt; }
        public void setCreatedAt(Date createdAt) { this.createdAt = createdAt; }
    }

    public static void main(String[] args) {
        User user = new User("jack", "secret123", new Date());
        String json = JSON.toJSONString(user);
        System.out.println(json);
    }
}

运行输出示例:

java 复制代码
{
  "user_name":"jack",
  "createdAt":"2025-05-06 14:12:33"
}

六、实战注意事项

  1. 优先级问题 :Fastjson 默认使用字段进行序列化,如果字段和 getter 都使用了 @JSONField,字段上的注解优先。

  2. transient 冲突transient 修饰的字段不会被序列化,即使加上了 @JSONField,也需要设置 SerializerFeature.WriteMapNullValue 才可能生效。

  3. 性能优化 :通过设置 ordinal 属性可以控制序列化顺序,从而在某些场景下优化网络传输结构。

  4. 避免与 Jackson 混用:项目中如果同时使用了 Fastjson 和 Jackson,要避免注解混淆导致序列化失效。


七、总结

@JSONField 是 Fastjson 提供的一个功能强大的注解,它允许开发者更灵活地控制对象的 JSON 映射行为。通过合理配置其属性,可以实现字段重命名、日期格式转换、序列化控制等多种功能,在企业级开发中非常实用。

如果你在项目中使用 Fastjson,掌握 @JSONField 的用法将大大提升你对 JSON 数据处理的掌控能力。

相关推荐
代码中介商1 小时前
C++ STL 容器完全指南(二):vector 深入与 stringstream 实战
开发语言·c++
scott.cgi2 小时前
Unity直接编译Java文件作为插件,导致失败的两个打包设置
java·unity·unity调用java·unity的java文件·unity的android插件·unity调用android·unity加载java代码
澈2076 小时前
C++并查集:高效解决连通性问题
java·c++·算法
郝学胜-神的一滴7 小时前
Qt 入门 01-01:从零基础到商业级客户端实战
开发语言·c++·qt·程序人生·软件构建
测试员周周7 小时前
【Appium 系列】第06节-页面对象实现 — LoginPage 实战
开发语言·前端·人工智能·python·功能测试·appium·测试用例
2401_873479407 小时前
运营活动被薅羊毛怎么防?用IP查询+设备指纹联动封堵漏洞
java·网络·tcp/ip·github
ShiJiuD6668889997 小时前
大事件板块一
java
摇滚侠7 小时前
@Autowired 和 @Resource 的区别
java·开发语言
Wy_编程8 小时前
go语言中的结构体
开发语言·后端·golang
SeaTunnel8 小时前
(八)收官篇 | 数据平台最后一公里:数据集成开发设计与上线治理实战
java·大数据·开发语言·白鲸开源