SpringMVC的@RequestBody注解使用fastjson反序列化枚举类型

1、使用mybatis-plus,指定枚举类所在的的包

SpringBoot工程在
application.yml中增加

mybatis-plus:
  type-enums-package: com.xxx.xxx.model.enums

2、实现mybatisplus提供的IEnum接口,重写getValue()方法

package com.xxx.xxx.model.enums;

import com.baomidou.mybatisplus.core.enums.IEnum;

/**
 * <p>
 * 用户状态枚举
 * </P>
 * @author frank
 * @date 2019/7/11 19:05
 */
public enum UserState implements IEnum {

    /**
     * 正常
     */
    NORMAL(10, "正常"),
    /**
     * 锁定
     */
    LOCKED(20, "锁定"),
    /**
     * 失效
     */
    INVALID(30, "失效"),

    /**
     * 异常
     * */
    ABNORMAL(40, "异常"),

    /**
     * 未激活
     * */
    NOT_ACTIVE(50, "未激活");

    private int value;

    private String desc;

    UserState(final int value, String desc) {
        this.value = value;
        this.desc = desc;
    }

    @Override
    public Integer getValue() {
        return this.value;
    }

    @Override
    public String toString(){
        return desc;
    }
}

3、将SpringMVC的JSON解析器设置为fastjson

package com.xxx.xxx.config.fastjson;

import java.math.BigInteger;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.ToStringSerializer;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;

/**
 * <p>
 * fastjson序列化配置
 * </P>
 * @author frank
 * @date 2019-10-12 18:33
 */
@Configuration
public class FastJsonMvcConfig implements WebMvcConfigurer {

    private static final String DEFAULT_CHARSET = "UTF-8";

    private static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:SS";

    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {

        FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();

        List<MediaType> mediaTypes = new ArrayList<>();
        mediaTypes.add(MediaType.APPLICATION_JSON);
        mediaTypes.add(MediaType.TEXT_HTML);
        mediaTypes.add(new MediaType("application", "xml"));
        mediaTypes.add(new MediaType("text", "xml"));
        mediaTypes.add(new MediaType("application", "*+xml"));
        mediaTypes.add(MediaType.ALL);
        fastJsonHttpMessageConverter.setSupportedMediaTypes(mediaTypes);

        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        fastJsonConfig.setCharset(Charset.forName(DEFAULT_CHARSET));
        fastJsonConfig.setDateFormat(DEFAULT_DATE_FORMAT);

        SerializerFeature[] serializerFeatures = new SerializerFeature[] {
                //格式化输出
                SerializerFeature.PrettyFormat,
                //输出空置
                SerializerFeature.WriteMapNullValue,
                //空集合输出空数组[]
                SerializerFeature.WriteNullListAsEmpty,
                //日期格式化
                SerializerFeature.WriteDateUseDateFormat,
                //枚举输出
                SerializerFeature.WriteEnumUsingToString
        };
        fastJsonConfig.setSerializerFeatures(serializerFeatures);

        SerializeConfig serializeConfig = SerializeConfig.globalInstance;
        serializeConfig.put(BigInteger.class, ToStringSerializer.instance);
        serializeConfig.put(Long.class, ToStringSerializer.instance);
        serializeConfig.put(Long.TYPE, ToStringSerializer.instance);
        fastJsonConfig.setSerializeConfig(serializeConfig);

        fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonConfig);

        converters.add(fastJsonHttpMessageConverter);
    }
}

4、使用fastjson反序列化枚举类型

如果是IEnum类型,则先根据getValue()进行匹配,然后根据toString()进行匹配,如果都没有匹配到,再按照名字或者枚举类的序号进行匹配。

package com.xxx.xxx.config.fastjson;

import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.parser.DefaultJSONParser;
import com.alibaba.fastjson.parser.JSONLexer;
import com.alibaba.fastjson.parser.JSONToken;
import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer;
import com.baomidou.mybatisplus.core.enums.IEnum;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Method;
import java.lang.reflect.Type;


/**
 * fastJson反序列化枚举类型
 *
 * @author frank
 * @date 2020/2/25 15:23
 */
@Slf4j
public class FastJsonEnumDeserializer implements ObjectDeserializer {

    @Override
    public <T> T deserialze(DefaultJSONParser parser, Type type, Object o) {
        final JSONLexer lexer = parser.lexer;
        final int token = lexer.token();
        Class cls = (Class) type;
        Object[] enumConstants = cls.getEnumConstants();
        if (IEnum.class.isAssignableFrom(cls)) {
            // IEnum类型
            try {
                // 根据getValue()进行取值
                Method getValueMethod = cls.getMethod("getValue");
                Class returnType = getValueMethod.getReturnType();
                if (Integer.class.equals(returnType) || int.class.equals(returnType)) {
                    if (token == JSONToken.LITERAL_INT) {
                        for (Object enumConstant : enumConstants) {
                            IEnum<Integer> baseEnum = (IEnum<Integer>) enumConstant;
                            Integer value = baseEnum.getValue();
                            if (lexer.intValue() == value) {
                                return (T) baseEnum;
                            }
                        }
                    }
                }
            }catch (NoSuchMethodException e){
                e.printStackTrace();
            }

            try {
                // 根据toString()进行取值
                Method getValueMethod = cls.getMethod("toString");
                Class returnType = getValueMethod.getReturnType();
                if (String.class.equals(returnType)) {
                    if (token == JSONToken.LITERAL_STRING) {
                        for (Object enumConstant : enumConstants) {
                            IEnum baseEnum = (IEnum) enumConstant;
                            String str = baseEnum.toString();
                            if (null != str && str.equals(lexer.stringVal())) {
                                return (T) baseEnum;
                            }
                        }
                    }
                }
            }catch (NoSuchMethodException e){
                e.printStackTrace();
            }
        }
        // 默认按名字或者按ordinal取值
        if (token == JSONToken.LITERAL_INT) {
            // 按ordinal取值
            int intValue = lexer.intValue();
            lexer.nextToken(JSONToken.COMMA);
            if (intValue < 0 || intValue > enumConstants.length) {
                throw new JSONException(String.format("parse enum %s error, value : %s", cls.getName(), intValue));
            }
            return (T) enumConstants[intValue];
        } else if (token == JSONToken.LITERAL_STRING) {
            // 按名字取值
            return (T) Enum.valueOf(cls, lexer.stringVal());
        }
        return null;
    }

    @Override
    public int getFastMatchToken() {
        return JSONToken.LITERAL_INT;
    }

}

5、在成员变量上增加 @JSONField注解,使用deserializeUsing指定反序列化类

    @JSONField(deserializeUsing = FastJsonEnumDeserializer.class)
package com.xxx.xxx.vo;

import com.alibaba.fastjson.annotation.JSONField;
import com.xxx.xxx.model.enums.UserState;
import com.xxx.xxx.config.fastjson.FastJsonEnumDeserializer;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
import java.util.List;

/**
 * @author frank
 * @date 2019/9/6
 */
@ApiModel
@Data
public class UserInfoVo implements Serializable {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "主键id")
    private String id;

    @ApiModelProperty(value = "用户账号")
    private String userAccount;

    @ApiModelProperty(value = "用户状态")
    @JSONField(deserializeUsing = FastJsonEnumDeserializer.class)
    private UserState userState;

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值