【问题标题】:JSON deserialization to Enum with Java 8, Spring Boot Starter 2.1.9 and Lombok 1.18.10使用 Java 8、Spring Boot Starter 2.1.9 和 Lombok 1.18.10 将 JSON 反序列化为 Enum
【发布时间】:2020-05-14 19:03:28
【问题描述】:

我正在尝试反序列化为枚举,但 JSON 值(小写)与枚举常量(大写)不同。

这是枚举:

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public enum ContractTypes {

  @JsonProperty("product")
  PRODUCT("product"), 
  @JsonProperty("service")
  SERVICE("service");

  private String value;
}

如您所见,我使用@JsonPropertyannotation 对元素进行了注释,以尝试将提供的值映射到合适的常量。

我还尝试使用@JsonValue 注释对属性value 进行注释。在这两种情况下,我都得到了相同的结果:

Field error in object 'createContractRequestDto' on field 'contractType': rejected value [product]; codes [typeMismatch.createContractRequestDto.contractType,typeMismatch.contractType,typeMismatch.enm.ContractTypes,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [createContractRequestDto.contractType,contractType]; arguments []; default message [contractType]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'enm.ContractTypes' for property 'contractType'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [enm.ContractTypes] for value 'product'; nested exception is java.lang.IllegalArgumentException: No enum constant enm.ContractTypes.product]]

为什么@JsonProperty@JsonValue 注释不起作用?我必须如何编写解决方案以将 JSON 值映射到合适的枚举元素?

【问题讨论】:

    标签: java json enums jackson jackson-databind


    【解决方案1】:

    我们还可以创建自定义转换器。

    public class ContractTypesConverter implements Converter<String, ContractTypes> {
    
       @Override
       public ContractTypes convert(String source) {
         return ContractTypes.valueOf(source.toUpperCase());
       }
    }
    

    这可以进一步写成这样(感谢lambda

    Converter<String, ContractTypes> converter = source -> ContractTypes.valueOf(source.toUpperCase());
    

    然后像这样用WebMvcConfigurer注册它

    @Configuration
    public class WebConfiguration implements WebMvcConfigurer {
    
       // ... other configurations
    
       @Override
       public void addFormatters(FormatterRegistry registry) {
          registry.addConverter(new ContractTypesConverter());
       }
    
    }
    

    【讨论】:

      【解决方案2】:

      这对我有用。不确定您在代码中遗漏了什么。

      @Getter
      public enum ContractTypes {
      
          PRODUCT("product"),
          SERVICE("service");
      
          private String value;
      
          ContractTypes(String value){
              this.value = value;
          }
      
          @JsonValue
          public String getValue() {
              return value;
          }
      }
      
      @NoArgsConstructor
      @Setter
      @Getter
      static class Holder {
          private ContractTypes contractTypes;
      }
      
      @Test
      public void test() throws IOException {
          Holder holder = new ObjectMapper().readValue("{\"contractTypes\":\"product\"}", Holder.class);
          assertEquals(ContractTypes.PRODUCT, holder.contractTypes);
      }
      

      【讨论】:

        【解决方案3】:

        这些注释适用于非枚举类型的属性。 您可以使用PRODUCT 之类的方式直接使用枚举,或者编写自定义反序列化器并将其用于反序列化注释属性。

        @JsonDeserialize(using = ContractTypesDeserializer.class)
        ContractTypes contractTypes;
        

        客户反序列化器实现

        public class ContractTypesDeserializer extends StdDeserializer<ContractTypes> {
          private static final long serialVersionUID = -4714891596189L;
        
          public ContractTypesDeserializer() {
            super ContractTypes.class);
          }
        
          protected ContractTypesDeserializer(Class ContractTypes> type) {super(type);}
        
          @Override
          public ContractTypes deserialize(JsonParser parser, DeserializationContext context)
              throws IOException, JsonProcessingException {
              return ContractTypes.valueOf(parser.getText().toUpperCase());
          }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-06-07
          • 1970-01-01
          • 2020-09-07
          • 1970-01-01
          • 1970-01-01
          • 2016-12-31
          • 2019-10-28
          • 2021-12-12
          相关资源
          最近更新 更多