1. ホーム
  2. java

Jacksonによるenumのデシリアライズ

2023-09-06 21:58:16

質問

私は Jackson 2.5.4 で enum をデシリアライズしようとして失敗しています。私の入力文字列はキャメルケースで、私は単純に標準の Enum 規則にマッピングしたいのです。

@JsonFormat(shape = JsonFormat.Shape.STRING)
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(toMap(s -> s.formatted, Function.<Status>identity()));

    private final String formatted;

    Status(String formatted) {
        this.formatted = formatted;
    }

    @JsonCreator
    public Status fromString(String string) {
        Status status = FORMAT_MAP.get(string);
        if (status == null) {
            throw new IllegalArgumentException(string + " has no corresponding value");
        }
        return status;
    }
}

また @JsonValue も試してみましたが、これは他の場所で報告されたオプションで、無駄でした。それらはすべてで吹き飛びます。

com.fasterxml.jackson.databind.exc.InvalidFormatException: Can not construct instance of ...Status from String value 'ready': value not one of declared Enum instance names: ...

私は何を間違えているのでしょうか?

どうすればいいのでしょうか?

EDITです。 Jackson 2.6以降では、以下のように @JsonProperty を使用して、シリアライズ/デシリアライズの値を指定することができます ( はこちら ):

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


(この回答の残りの部分は、古いバージョンのJacksonでも有効です)

あなたは @JsonCreator を受け取る静的メソッドにアノテートします。 String 引数を受け取る静的メソッドにアノテーションを付けることができます。これは、Jackson が ファクトリーメソッド :

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));
    }
}

これはテストです。

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

ファクトリーメソッドは String を想定しているので、JSONで有効な文字列の構文、つまり値を引用符で囲むことを使わなければなりません。