前言
Java
后端开发中,我们经常需要处理 JSON
序列化和反序列化的问题。Spring
框架默认使用 Jackson
作为 JSON
处理库,但在某些情况下,我们也可能会使用 Fastjson
来处理特定的序列化需求。由于这两种库的注解不完全兼容,因此在同一个项目中同时使用它们时,可能会遇到一些问题。
问题
假设你有一个实体类 User
,其中包含一些字段,并且你希望在某些情况下忽略某些字段,或者自定义序列化方式。你在字段上同时使用了 Jackson
或者 Fastjson
的注解,如下所示:
Jackson:
这种情况下,在 controller
层返回给前端,属性忽略注解(@JsonIgnore
)和序列化方式注解(@JsonSerialize
)是会生效的,但是使用 Fastjson
去序列化的时候就不生效!
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.io.Serializable;
public class User implements Serializable {
private Long id;
@JsonIgnore
private String password;
@JsonSerialize(using = StringSerializer.class)
private Date createdAt;
}
Fastjson:
这种情况下,在 Fastjson
序列化的时候可以正常处理字段属性忽略和序列方式,但是在 controller
层无效!
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.io.Serializable;
public class User implements Serializable {
private Long id;
@JSONField(serialize = false, deserialize = false)
private String password;
@JSONField(format = "string")
private Date createdAt;
}
解决方案
两种库的注解同时放置到属性字段上
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.io.Serializable;
public class User implements Serializable {
private Long id;
@JsonIgnore
@JSONField(serialize = false, deserialize = false)
private String password;
@JsonSerialize(using = StringSerializer.class)
@JSONField(format = "string")
private Date createdAt;
}
自定义复合注解
为了在同一个项目中同时支持 Jackson 和 Fastjson,并且避免重复编写相同的注解,我们可以创建自定义注解来实现通用性。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.METHOD })
@com.fasterxml.jackson.annotation.JsonIgnore
@com.alibaba.fastjson.annotation.JSONField(serialize = false, deserialize = false)
public @interface IgnoreField {
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.METHOD })
@com.fasterxml.jackson.databind.annotation.JsonSerialize(using = StringSerializer.class)
@com.alibaba.fastjson.annotation.JSONField(format = "string")
public @interface CustomStringSerializer {
}
序列化的时候使用统一的库
序列化的时候直接用ObjectMapper就行了,保持和 Spring 整合的 Jackson 统一就行了