当实体类中的属性为枚举类型时,将其序列化成json字符串传给前端,传递的应该是有效的值而不是枚举常量。
1. Get-Started
@Data
public class Student {
private Long id;
private String userName;
private String telephone;
private String email;
private SexEnum sex;
}
public enum SexEnum {
UNKNOWN(0, "未知"),
MALE(1001, "男性"),
FEMALE(1002, "女性"),
NOMALE(1003, "妖怪");
private int code;
private String desc;
SexEnum(int code, String desc) {
this.code = code;
this.desc = desc;
}
}
2. 问题引出
2.1 序列化
当一个对象为
Student(id=1, userName=hahaha, telephone=null, email=hahaha@233.com, sex=FEMALE)
将其序列化为json字符串传递给前端时,sex字段应该转成下面哪种形式?
{"id":1,"userName":"hahaha","telephone":"12312311122","email":"hahaha@233.com","sex":"FEMALE"}
{"id":1,"userName":"hahaha","telephone":"12312311122","email":"hahaha@233.com","sex":1002}
显然,枚举量sex=FEMALE应该转换成int型1002。
code为有效值,在上面加个 @JsonValue 注解就行。
2.2 反序列化
同样,
当前端传过来的json字符串为
{"id":1,"userName":"hahaha","telephone":"12312311122","sex":1002,"email":"hahaha@233.com"}
时,后端应该序列化为
Student(id=1, userName=hahaha, telephone=null, email=hahaha@233.com, sex=FEMALE)
对象,否则会报错
因此需要用 @JsonCreator 注解自定义反序列化方式,示例如下
@JsonCreator
public static SexEnum forValue(Integer value) {
SexEnum[] values = SexEnum.values();
return Stream.of(values).filter(it -> it.getCode()==(value)).findAny().orElse(UNKNOWN);
}
3. 改进序列化后enum代码
@Getter
public enum SexEnum {
UNKNOWN(0, "未知"),
MALE(1001, "男性"),
FEMALE(1002, "女性"),
NOMALE(1003, "妖怪");
@JsonValue
private int code;
private String desc;
SexEnum(int code, String desc) {
this.code = code;
this.desc = desc;
}
@JsonCreator
public static SexEnum forValue(Integer value) {
SexEnum[] values = SexEnum.values();
return Stream.of(values).filter(it -> it.getCode()==(value)).findAny().orElse(UNKNOWN);
}
}
4. 测试
import com.alibaba.nacos.common.utils.JacksonUtils;
import org.junit.jupiter.api.Test;
public class JacksonTest {
// 序列化实体类,即后端to前端的过程。
@Test
public void test01(){
Student student = new Student();
student.setId(1L);
student.setEmail("hahaha@233.com");
student.setTelephone("12312311122");
student.setUserName("hahaha");
student.setSex(SexEnum.FEMALE);
String json = JacksonUtils.toJson(student);
System.out.println(json);
}
// @JsonCreator 反序列化
@Test
public void test02(){
String json = "{\"id\":1,\"userName\":\"hahaha\",\"telphone\":\"12312311122\",\"sex\":1002,\"email\":\"hahaha@233.com\"}";
Student obj = JacksonUtils.toObj(json, Student.class);
System.out.println(obj);
}
}
需要注意的是,以上的注解存在于依赖包com.fasterxml.jackson.annotation下,因此有些不是基于com.fasterxml.jackson的json序列化工具类可能不支持这两个注解。
比如说com.alibaba.fastjson.JSON就不支持这两个注解。