使用 Jackson 自定义枚举常量名称

Customizing enum constant names with Jackson

我有一个枚举定义为

public enum Locale {
  EN_US, ES_MX
}

然而,这些语言环境在数据中被写为带连字符的小写字符串,如 en-uses-mx

有没有办法将这些小写字符串映射到相应的枚举常量?喜欢 en-usEN_US?

编辑 让我提供更多信息。我有一个对象 class.

public class Song {
  private Map<Locale, String> songName;
  private int durationMillis;
}

歌曲的名称可能因语言环境而异。所以我在各种语言环境中为歌曲名称创建了一个映射。

我有一个包含歌曲信息的 JSON 文件。内容如下:

{
  "songs": [
    {
      "songName": {"en-us":"Song name in US english", "es-mx": "Song name in Spanish"},
      "durationMillis": 100000
    },
    {
      "songName": {"en-us": "another song name -  English"},
      "durationMillis": 200000
    }
  ]
}

我再定义一个class.

public class Songs {
  private Set<Song> songs;
}

我使用 FasterXml 的 ObjectMapper 加载 JSON 作为 Songs class.

的对象
Songs songs = objectMapper.readValue(jsonStr, Songs.class);

上面这行现在崩溃了,因为 ObjectMapper 无法将 en-us 字符串映射到 Locale.EN_US

我总是可以编辑枚举并将其定义为

public enum Locale {
  EN_US("en-us"),
  ES_MX("es-mx");

  private String value;
  Locale(String val){
    value = val;
  }
}

但我在某处看到了一种更聪明的方法,它将小写连字符字符串转换为大写下划线文字。你能告诉我那个解决方案吗?

我需要一个解决方案,以便 FasterXml 的 ObjectMapper 可以将字符串映射到枚举。

因为 Jackson 2.6, you can annotate your enum constants with @JsonProperty to give them a custom name. The javadoc 状态

Starting with Jackson 2.6 this annotation may also be used to change serialization of Enum like so:

public enum MyEnum {
    @JsonProperty("theFirstValue") THE_FIRST_VALUE,
    @JsonProperty("another_value") ANOTHER_VALUE;
}

在你的情况下,你会使用

public enum Locale {
  @JsonProperty("en-us") EN_US, @JsonProperty("es-mx") ES_MX
}

或者,假设所有枚举常量都遵循相同的命名模式,您可以使用 @JsonValue。在您的枚举类型中定义一个用 @JsonValue 注释的实例方法,并使用您的命名策略实现它。例如,

@JsonValue
public String forJackson() {
    return name().toLowerCase().replace('_', '-');
}

您将受益于

when use for Java enums, one additional feature is that value returned by annotated method is also considered to be the value to deserialize from, not just JSON String to serialize as. This is possible since set of Enum values is constant and it is possible to define mapping, but can not be done in general for POJO types; as such, this is not used for POJO deserialization.

它将用于序列化和反序列化。


避免使用已经出现在 JDK 中的名称来命名您的类型。 Java 已经提供了常用的 Locale 类型。考虑重命名您的 class。