【问题标题】:Spring Boot enum JSON serializerSpring Boot 枚举 JSON 序列化程序
【发布时间】:2020-11-10 15:07:15
【问题描述】:

下面是我要转换成 JSON 的对象;

public class TestDto{
    private ResponseType responseType;
    private Long id;
    private String name;
}

下面的ResponseType是一个枚举;

public enum ResponseType{ 
    TEST1("test message 1"), TEST2("test message 2"), TEST3("test message 3");
    private String message;
}

下面是我要创建的 JSON:

{"code":"TEST1", "message":"test message 1", "id":1, "name":"name"}

JSON 响应中的代码指向枚举的名称,JSON 响应中的消息指向枚举的 message 字段。

有什么办法吗?

【问题讨论】:

  • 是的。查看 Jackson 库中的 JSON 支持。祝你好运!

标签: java json spring-boot enums


【解决方案1】:

最简单的方法是将派生的 getter/setter 添加到 TestDto,并禁止 responseType 字段的 JSON 序列化。

class TestDto {
    private ResponseType responseType;
    private Long id;
    private String name;

    @JsonIgnore // Suppress JSON serialization
    public ResponseType getResponseType() {
        return this.responseType;
    }
    public void setResponseType(ResponseType responseType) {
        this.responseType = responseType;
    }

    public String getCode() { // Derived getter for "code" property
        return this.responseType.name();
    }
    public void setCode(String code) { // Derived setter for "code" property
        this.responseType = (code == null ? null : ResponseType.valueOf(code));
    }

    public String getMessage() { // Derived getter for "message" property
        return this.responseType.getMessage();
    }
    @Deprecated // Shouldn't be called by Java code, since it's a dummy stub method
    @SuppressWarnings("unused")
    public void setMessage(String message) { // Derived setter for "message" property
        // Ignore value
    }

    public Long getId() {
        return this.id;
    }
    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return this.name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

双向测试

TestDto testDto = new TestDto();
testDto.setResponseType(ResponseType.TEST1);
testDto.setId(1L);
testDto.setName("name");

ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(testDto);
System.out.println(json);

TestDto testDto2 = mapper.readValue(json, TestDto.class);
System.out.println(testDto2.getResponseType());
System.out.println(testDto2.getId());
System.out.println(testDto2.getName());

输出

{"id":1,"name":"name","message":"test message 1","code":"TEST1"}
TEST1
1
name

【讨论】:

    【解决方案2】:

    我已经更新了我之前的答案,因为它不正确。您可以使用@JsonFormat(shape = JsonFormat.Shape.OBJECT) 指示枚举应该像对象一样被序列化(基于getter)。

        @JsonFormat(shape = JsonFormat.Shape.OBJECT)
        public enum ResponseType{
           TEST1("test message 1"), TEST2("test message 2"), TEST3("test message 3");
           private String message;
    
           ResponseType(String message) {
              this.message = message;
           }
    
           public String getMessage() {
              return message;
           }
    
           public String getCode() {
              return this.toString();
          }
       }
    

    之后,您还必须在 Enum 字段上使用 @JsonUnwrapped 以避免将其字段序列化为对象。

        public static class TestDto {
           @JsonUnwrapped private ResponseType responseType;
           private Long id;
           private String name;
        }
    

    运行以下代码

        TestDto testDto = new TestDto(ResponseType.TEST1, 1234356L, "First Response");
        result = mapper.writeValueAsString(testDto);
        System.out.println(result);
    

    我得到结果{"message":"test message 1","code":"TEST1","id":1234356,"name":"First Response"}

    【讨论】:

    • 不会为 1 个枚举输出 2 个属性:response 字段 -> "code""message"
    • 我误解了请求,将更新答案以匹配问题。
    • @Slimu 带有这个注释我得到了没有枚举值名称的 json {"message":"test message 1", "id":1234356,"name":"First Response"}
    • 你是否在枚举中添加了显式getter?
    猜你喜欢
    • 2012-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-01
    • 1970-01-01
    • 2017-04-10
    • 2014-08-20
    相关资源
    最近更新 更多