【Spring Boot】如何处理前后端枚举值的序列化

假设我们定义了如下的枚举类,包含code和msg两个属性。

package cn.bugkit.serialization.components;

import java.security.InvalidParameterException;

/**
 * @author bugkit
 * @since 2022.2.25
 */
public enum Result {

    SUCCESS(0,"SUCCESS"),
    FAIL(-1,"FAIL");

    int code;
    String msg;

    Result(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public static Result valueOf(int code){
        Result[] values = values();
        for (Result result : values) {
            if (result.getCode() == code) {
                return result;
            }
        }
        throw new InvalidParameterException("Invalid Code");
    }
}

Spring Boot Jackson枚举值默认是通枚举常量的名字来序列化和反序列化的。

假设现在前端要求前后端的通信通过code属性进行。我们应该怎么做呢?

那就要用到Spring Boot提供的@JsonComponent注解了。

下面我们一起看看完整的实例吧。

首先是controller,提供了入参(反序列化)和结果返回(序列化)的例子。

/**
 * @author bugkit
 * @since 2022.2.25
 */
@RestController
public class EnumController {

    /**
     * 入参的result字段是 -1 - fail,结果是0 - success
     * @param response
     * @return
     */
    @PostMapping("test")
    public HttpResponse testSerialize(@RequestBody HttpResponse response) {
        System.out.println(response);
        return new HttpResponse(Result.SUCCESS, null);
    }

}

下面我们看看HttpResponse,包含属性result和数据data

/**
 * @author bugkit
 * @since 2022.2.25
 */
public class HttpResponse {

    private Result result;
    private Object data;


    public HttpResponse(Result result, Object data) {
        this.result = result;
        this.data = data;
    }

    public Result getResult() {
        return result;
    }

    public void setResult(Result result) {
        this.result = result;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    @Override
    public String toString() {
        return "HttpResponse{" +
                "result=" + result +
                ", data=" + data +
                '}';
    }
}

最后再看看关键的地方,标注Result所使用的序列化和反序列化类

/**
 * @author bugkit
 * @since 2022.2.25
 */
@JsonComponent
public class WenSerialization {

    /**
     * 序列化,即将Java对象转为JSON,用于将Java对象转为前端所需的结果,此处只传输Result的code字段
     */
    public static class ResultSerializer extends JsonSerializer {

        @Override
        public void serialize(Result value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
            gen.writeNumber(value.getCode());
        }
    }

    /**
     * 反序列化,将JSON转为Java对象,用于接收前端参数
     */
    public static class ResultDeSerializer extends JsonDeserializer {

        @Override
        public Result deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
            ObjectCodec codec = p.getCodec();
            JsonNode treeNode = codec.readTree(p);
            int code = treeNode.intValue();
            return Result.valueOf(code);
        }
    }
}

最后我们来看看测试结果:

入参

{
    "result": -1,
    "data": "data"
}

控制台打印

2022-02-25 10:16:57.583  INFO 1324 --- [nio-8080-exec-2] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2022-02-25 10:16:57.584  INFO 1324 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2022-02-25 10:16:57.584  INFO 1324 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : Completed initialization in 0 ms
HttpResponse{result=FAIL, data=data}

返回结果

{
    "result": 0,
    "data": null
}

注意:该方式只针对使用了spring boot自带的jackson才生效。

序列化其他自定义对象也是同理

代码地址:https://github.com/bennetty74...

你可能感兴趣的:(【Spring Boot】如何处理前后端枚举值的序列化)