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

Nik*_*Nik 3 java enums jackson fasterxml

我有一个枚举定义为

public enum Locale {
  EN_US, ES_MX
}
Run Code Online (Sandbox Code Playgroud)

但是,这些语言环境被写为带有连字符的小写字符串en-uses-mx数据.

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

编辑 让我提供更多信息.我有以下课程的对象.

public class Song {
  private Map<Locale, String> songName;
  private int durationMillis;
}
Run Code Online (Sandbox Code Playgroud)

歌曲的名称可能因Locale而异.所以我在各种Locales中创建了一个歌曲名称的地图.

我有一个包含歌曲信息的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
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

我定义了另一个类.

public class Songs {
  private Set<Song> songs;
}
Run Code Online (Sandbox Code Playgroud)

我使用FasterXml ObjectMapper来加载JSON作为Songs类的对象.

Songs songs = objectMapper.readValue(jsonStr, Songs.class);
Run Code Online (Sandbox Code Playgroud)

此上面的行已经崩溃,因为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;
  }
}
Run Code Online (Sandbox Code Playgroud)

但我在某处看到了一种更聪明的方法,它将小写的带连字符的字符串转换为大写的下划线字面值.你能指点我的解决方案吗?

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

Sot*_*lis 12

Jackson 2.6开始,您可以使用@JsonProperty自定义名称来注释枚举常量.该javadoc的状态

从Jackson 2.6开始,这个注释也可以用来改变Enum类似的序列化:

public enum MyEnum {
    @JsonProperty("theFirstValue") THE_FIRST_VALUE,
    @JsonProperty("another_value") ANOTHER_VALUE;
}
Run Code Online (Sandbox Code Playgroud)

在你的情况下,你会使用

public enum Locale {
  @JsonProperty("en-us") EN_US, @JsonProperty("es-mx") ES_MX
}
Run Code Online (Sandbox Code Playgroud)

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

@JsonValue
public String forJackson() {
    return name().toLowerCase().replace('_', '-');
}
Run Code Online (Sandbox Code Playgroud)

你得到了很好的好处

当用于Java枚举时,另一个特性是注释方法返回的值也被认为是反序列化的值,而不仅仅是要序列化的JSON字符串.这是可能的,因为Enum值的集合是常量并且可以定义映射,但是对于POJO类型通常不能完成; 因此,这不用于POJO反序列化.

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


避免使用已经出现在JDK中的名称来命名类型.Java已经提供了一种常用的Locale类型.考虑重命名你的课程.