概述
注意正确的使用枚举
RPC框架大多数会采用JSON的格式进行数据传输
而JSON在反序列化的过程中,对于一个枚举类型,会尝试调用对应的枚举类的valueOf方法来获取到对应的枚举,如果从枚举类中找不到对应的枚举项的时候,就会抛出IllegalArgumentException异常
建议
- 考虑版本兼容性问题
- 接口返回时将枚举转换成String类型返回
常用json注解
@JsonIgnoreProperties:
此注解是类注解,作用是在json序列化时将Java bean中的某些属性忽略掉,序列化和反序列化都受影响。
@JsonIgnore:
此注解用于属性或者方法上(最好是属性上),作用和上面的@JsonIgnoreProperties一样。
@JsonFormat:
此注解用于属性或者方法上(最好是属性上),可以方便的把Date类型直接转化为我们想要的模式,比如@JsonFormat(pattern = “yyyy-MM-dd HH-mm-ss”)
@JsonSerialize:
此注解用于属性或者getter方法上,用于在序列化时嵌入我们自定义的序列化器,比如序列化一个double时在其后面限制两位小数点。
@JsonDeserializ:
此注解用于属性或者setter方法上,用于在反序列化时嵌入我们自定义的反序列化器,比如反序列化一个Date类型的时间字符串。
@JsonCreator与@JsonProperty:
该注解的作用就是指定反序列化时替代无参构造函数,构造方法的参数前面需要加上@JsonProperty注解。
json序列化-枚举转换
链接: 整合SpringMVC之自定义JSON序列化器和反序列化器.
package com.zm.constant;
/**
* 通用枚举接口
* @param <E>
* @param <T>
*/
public interface BaseEnum<E extends Enum<?>, T> {
T getValue();
String getDisplayName();
static <T extends Enum<T>> T valueOfEnum(Class<T> enumClass, Integer value) {
if (value == null)
throw new IllegalArgumentException("DisplayedEnum value should not be null");
if (enumClass.isAssignableFrom(BaseEnum.class))
throw new IllegalArgumentException("illegal DisplayedEnum type");
T[] enums = enumClass.getEnumConstants();
for (T t: enums) {
BaseEnum displayedEnum = (BaseEnum)t;
if (displayedEnum.getValue().equals(value))
return (T) displayedEnum;
}
throw new IllegalArgumentException("cannot parse integer: " + value + " to " + enumClass.getName());
}
}
package com.zm.constant;
public enum PayTypeEnum implements BaseEnum<PayTypeEnum,Integer>{
/**
*现金支付(1)
*/
CASH(1, "现金支付"),
/**
* 扫码支付(2)
*/
SCAN(2, "扫码支付"),
/**
* 会员余额支付(3)
*/
VIP(3, "会员余额支付"),
;
private Integer value;
private String displayName;
PayTypeEnum(Integer value,String displayName) {
this.value=value;
this.displayName=displayName;
}
public Integer getValue() {
return value;
}
public void setValue(Integer value) {
this.value = value;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
}
package com.zm.constant;
import com.baomidou.mybatisplus.annotation.IEnum;
public enum PersonType implements IEnum<Integer>,BaseEnum {
student(1, "学生"),
teacher(2, "教师"),
;
private Integer value;
private String displayName;
PersonType(Integer value, String displayName) {
this.value = value;
this.displayName = displayName;
}
public Integer getValue() {
return value;
}
public void setValue(Integer value) {
this.value = value;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
}
package com.zm.config;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.*;
import com.zm.constant.BaseEnum;
import org.springframework.beans.BeanUtils;
import org.springframework.boot.jackson.JsonComponent;
import java.io.IOException;
@JsonComponent
public class Example {
/**
* 自定义序列化器 @RestController @ResponseBody
*/
public static class Serializer extends JsonSerializer<BaseEnum> {
/**
* 序列化操作,继承JsonSerializer,重写Serialize函数 返回前端的值
*/
@Override
public void serialize(BaseEnum value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeString(value.getDisplayName());
}
}
/**
* 自定义反序列化器 接收前端的值 @RequestBody
*/
public static class Deserializer extends JsonDeserializer<BaseEnum> {
@Override
public BaseEnum deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException{
JsonNode value = jsonParser.getCodec().readTree(jsonParser);
// 获取到当前的json key 名称
String currentName = jsonParser.currentName();
System.out.println(currentName);
// 获取到当前的json转换的对象
Object currentValue = jsonParser.getCurrentValue();
System.out.println(currentValue);
// 获取当前对象key名称相同的属性类
Class findPropertyType = BeanUtils.findPropertyType(currentName, currentValue.getClass());
// 属性为枚举
if (findPropertyType.isEnum()) {
BaseEnum[] enumConstants = (BaseEnum[]) findPropertyType.getEnumConstants();
for (BaseEnum e : enumConstants) {
if (e.getValue().equals(value.asInt())) {
return e;
}
}
}
// 否则返回空
return null;
}
}
}
package com.zm.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.zm.config.Example;
import com.zm.constant.PayTypeEnum;
import com.zm.constant.PersonType;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* 学生信息表
* </p>
*
* @author zhoum
* @since 2021-10-23
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("label")
public class LabelEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* ID
*/
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
/**
* 名称
*/
private String name;
/**
* 排序号
*/
private Integer sort;
/**
* 乐观锁
*/
@Version
private Integer version;
@TableLogic
private Boolean deleted;
/**
* 支付类型
*/
@JsonSerialize(using = Example.Serializer.class)
@JsonDeserialize(using = Example.Deserializer.class)
@TableField("pay_type")
private PayTypeEnum payType;
/**
* 学生类型
*/
@JsonSerialize(using = Example.Serializer.class)
@JsonDeserialize(using = Example.Deserializer.class)
@TableField("person_type")
private PersonType personType;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
private Date createTime;
/**
* 更新时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
}
import com.zm.entity.LabelEntity;
import com.zm.mapper.LabelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
public class Test11 {
@Autowired
private LabelMapper labelMapper;
@PostMapping("test11")
public LabelEntity test2(@RequestBody LabelEntity LabelEntity){
System.out.println(LabelEntity);
LabelEntity labelEntitie = labelMapper.selectById("16");
return labelEntitie;
}
}
get请求枚举转换 实现Converter完成String到IEnum的转换
链接: SpringMVC中将前端请求参数转为枚举类并将响应信息中的枚举类转为对应的值.
package com.zm.config;
import com.zm.constant.BaseEnum;
import org.springframework.util.StringUtils;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.ConverterFactory;
import org.springframework.stereotype.Component;
/**
* 枚举转换工厂
*/
@Component
public class EnumConvertFactory implements ConverterFactory<String, BaseEnum> {
@Override
public <T extends BaseEnum> Converter<String, T> getConverter(Class<T> targetType) {
return new StringToIEnum<>(targetType);
}
private static class StringToIEnum<T extends BaseEnum> implements Converter<String, T> {
private Class<T> targerType;
public StringToIEnum(Class<T> targerType) {
this.targerType = targerType;
}
@Override
public T convert(String source) {
if(StringUtils.isEmpty(source)){
return null;
}
for (T t : targerType.getEnumConstants()) {
if (source.equals(String.valueOf(t.getValue()))) {
return t;
}
}
return null;
}
}
}
package com.zm.config;
import org.springframework.format.FormatterRegistry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
@Autowired
private EnumConvertFactory enumConvertFactory;
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverterFactory(enumConvertFactory);
}
}
@GetMapping("test11")
public LabelEntity test1(LabelEntity LabelEntity){
System.out.println("getPayType:"+LabelEntity.getPayType().getDisplayName());
System.out.println("getPersonType:"+LabelEntity.getPersonType().getDisplayName());
LabelEntity labelEntitie = labelMapper.selectById("16");
return labelEntitie;
}
long类型精度丢失
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import org.springframework.format.FormatterRegistry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.List;
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
@Autowired
private EnumConvertFactory enumConvertFactory;
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
ObjectMapper objectMapper = new ObjectMapper();
/**
* 序列换成json时,将所有的long变成string
* 因为js中得数字类型不能包含所有的java long值
*/
SimpleModule simpleModule = new SimpleModule();
simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
objectMapper.registerModule(simpleModule);
jackson2HttpMessageConverter.setObjectMapper(objectMapper);
converters.add(0,jackson2HttpMessageConverter);
}
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverterFactory(enumConvertFactory);
}
}
日期格式化
链接: VO中@RequestBody接收Date参数注意.
参考链接
链接: 两个坑:long类型精度丢失,枚举类序列化和反序列化问题.
链接: 枚举与json的序列化/反序列化.
最后
以上就是大气纸飞机为你收集整理的整合SpringMVC之自定义JSON序列化器和反序列化器-枚举转换的全部内容,希望文章能够帮你解决整合SpringMVC之自定义JSON序列化器和反序列化器-枚举转换所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复