Deserializing an enum with Jackson

后端 未结 6 955
孤城傲影
孤城傲影 2020-12-02 16:35

I\'m trying and failing to deserialize an enum with Jackson 2.5.4, and I don\'t quite see my case out there. My input strings are camel case, and I want to simply map to sta

相关标签:
6条回答
  • 2020-12-02 16:57
    @JsonCreator
    public static Status forValue(String name)
    {
        return EnumUtil.getEnumByNameIgnoreCase(Status.class, name);
    }
    

    Adding this static method would resolve your problem of deserializing

    0 讨论(0)
  • 2020-12-02 16:58

    You could use @JsonCreator annotation to resolve your problem. Take a look at https://www.baeldung.com/jackson-serialize-enums, there's clear enough explanation about enum and serialize-deserialize with jackson lib.

    0 讨论(0)
  • 2020-12-02 17:09

    This is probably a faster way to do it:

    public enum Status {
     READY("ready"),
     NOT_READY("notReady"),
     NOT_READY_AT_ALL("notReadyAtAll");
    
     private final String formatted;
    
     Status(String formatted) {
       this.formatted = formatted;
     }
    
     @Override
     public String toString() {
       return formatted;
     }
    }
    
    public static void main(String[] args) throws IOException {
      ObjectMapper mapper = new ObjectMapper();
      ObjectReader reader = mapper.reader(Status.class);
      Status status = reader.with(DeserializationFeature.READ_ENUMS_USING_TO_STRING).readValue("\"notReady\"");
      System.out.println(status.name());  // NOT_READY
    }
    
    0 讨论(0)
  • 2020-12-02 17:09

    The solutions on this page work only for single field and @JsonFormat(shape = JsonFormat.Shape.NATURAL) (default format)

    this works for multiple fields and @JsonFormat(shape = JsonFormat.Shape.OBJECT)

    @JsonFormat(shape = JsonFormat.Shape.OBJECT)
    public enum PinOperationMode {
        INPUT("Input", "I"),
        OUTPUT("Output", "O")
        ;
    
        private final String mode;
        private final String code;
    
        PinOperationMode(String mode, String code) {
            this.mode = mode;
            this.code = code;
        }
    
        public String getMode() {
            return mode;
        }
    
        public String getCode() {
            return code;
        }
    
        @JsonCreator
        static PinOperationMode findValue(@JsonProperty("mode") String mode, @JsonProperty("code") String code) {
            return Arrays.stream(PinOperationMode.values()).filter(pt -> pt.mode.equals(mode) && pt.code.equals(code)).findFirst().get();
        }
    }
    
    0 讨论(0)
  • 2020-12-02 17:10

    For whoever is searching for enums with integer json properties. Here is what worked for me:

    enum class Status (private val code: Int) {
        PAST(0),
        LIVE(2),
        UPCOMING(1);
        companion object {
            private val codes = Status.values().associateBy(Status::code)
            @JvmStatic @JsonCreator fun from (value: Int) = codes[value]
        }
    }
    
    0 讨论(0)
  • 2020-12-02 17:11

    EDIT: Starting from Jackson 2.6, you can use @JsonProperty on each element of the enum to specify its serialization/deserialization value (see here):

    public enum Status {
        @JsonProperty("ready")
        READY,
        @JsonProperty("notReady")
        NOT_READY,
        @JsonProperty("notReadyAtAll")
        NOT_READY_AT_ALL;
    }
    

    (The rest of this answer is still valid for older versions of Jackson)

    You should use @JsonCreator to annotate a static method that receives a String argument. That's what Jackson calls a factory method:

    public enum Status {
        READY("ready"),
        NOT_READY("notReady"),
        NOT_READY_AT_ALL("notReadyAtAll");
    
        private static Map<String, Status> FORMAT_MAP = Stream
            .of(Status.values())
            .collect(Collectors.toMap(s -> s.formatted, Function.identity()));
    
        private final String formatted;
    
        Status(String formatted) {
            this.formatted = formatted;
        }
    
        @JsonCreator // This is the factory method and must be static
        public static Status fromString(String string) {
            return Optional
                .ofNullable(FORMAT_MAP.get(string))
                .orElseThrow(() -> new IllegalArgumentException(string));
        }
    }
    

    This is the test:

    ObjectMapper mapper = new ObjectMapper();
    
    Status s1 = mapper.readValue("\"ready\"", Status.class);
    Status s2 = mapper.readValue("\"notReadyAtAll\"", Status.class);
    
    System.out.println(s1); // READY
    System.out.println(s2); // NOT_READY_AT_ALL
    

    As the factory method expects a String, you have to use JSON valid syntax for strings, which is to have the value quoted.

    0 讨论(0)
提交回复
热议问题