Java 一种将枚举与JSON有效负载中绑定的值解耦的干净方法,以便它们更易于重用?

Java 一种将枚举与JSON有效负载中绑定的值解耦的干净方法,以便它们更易于重用?,java,json,enums,jackson,jackson-databind,Java,Json,Enums,Jackson,Jackson Databind,我从其他答案中了解到,要序列化和反序列化Jackson中不同基础值的枚举,我必须在enum类中执行以下操作: public enum LanguageType { JSON("json"), HTML("html"); private String key; LanguageType(String key) { this.key = key; } @JsonCreator public static Language

我从其他答案中了解到,要序列化和反序列化Jackson中不同基础值的枚举,我必须在enum类中执行以下操作:

public enum LanguageType {
    JSON("json"), 
    HTML("html");

    private String key;

    LanguageType(String key) {
        this.key = key;
    }

    @JsonCreator
    public static LanguageType fromString(String key) {
        return key == null
                ? null
                : LanguageType.valueOf(key.toUpperCase());
    }

    @JsonValue
    public String getKey() {
        return key;
    }
}
通过这种方式,Jackson可以在序列化和反序列化期间将enum
LanguageType.JSON
绑定到值
JSON
,将
LanguageType.HTML
绑定到值
HTML

然而,这样做的问题是,在我看来,在某种程度上,我会将JSON有效负载的字段耦合到枚举中

在上面的示例中,当JSON负载如下所示时,它可能会工作:

{
   "language": "html"
}
{
   "title": "Some Title",
   "language": "lang_html"
}
public enum LanguageType2 {
    JSON("lang_json"), 
    HTML("lang_html");

    private String key;

    LanguageType2(String key) {
        this.key = key;
    }

    @JsonCreator
    public static LanguageType2 fromString(String key) {
        return key == null
                ? null
                : LanguageType2.valueOf(key.toUpperCase());
    }

    @JsonValue
    public String getKey() {
        return key;
    }
}
但是,如果有另一个负载也有
语言
字段,我们可以使用
语言类型
枚举用于相同目的,但在其字段中使用不同的值,则不能重复使用
语言类型

例如,如果来自另一个服务的另一个JSON负载具有以下内容:

{
   "language": "html"
}
{
   "title": "Some Title",
   "language": "lang_html"
}
public enum LanguageType2 {
    JSON("lang_json"), 
    HTML("lang_html");

    private String key;

    LanguageType2(String key) {
        this.key = key;
    }

    @JsonCreator
    public static LanguageType2 fromString(String key) {
        return key == null
                ? null
                : LanguageType2.valueOf(key.toUpperCase());
    }

    @JsonValue
    public String getKey() {
        return key;
    }
}
在另一个JSON负载中,
LanguageType
enum不能被重用,因为键值用于第一个JSON负载的语言字段

当然,我可以为此重新创建另一个
LanguageType2
enum,如下所示:

{
   "language": "html"
}
{
   "title": "Some Title",
   "language": "lang_html"
}
public enum LanguageType2 {
    JSON("lang_json"), 
    HTML("lang_html");

    private String key;

    LanguageType2(String key) {
        this.key = key;
    }

    @JsonCreator
    public static LanguageType2 fromString(String key) {
        return key == null
                ? null
                : LanguageType2.valueOf(key.toUpperCase());
    }

    @JsonValue
    public String getKey() {
        return key;
    }
}
现在这可以工作了,但感觉不对,因为我重复了整个枚举的99%,因为它与第一个JSON负载绑定。现在,在我的应用程序(非JSON部分)中,我刚刚引入了一个新的困惑,即在我的逻辑中是使用
LanguageType
还是
LanguageType2


我如何使我的枚举更具可重用性,以便它在Jackson和我的应用程序中仍然可以工作,而不需要所有这些与实际有效负载字段本身相关的附加细节?

如何创建
私有列表密钥
,并为枚举提供表示给定枚举的所有类型值:
JSON(Arrays.asList(“JSON”,“JSON_html”))
?您需要在
fromString
方法中使用这些值。在
getKey
方法中,您总是会返回列表中的第一个键。@MichałZiober这可能行得通,但我还是在枚举中混合了与JSON负载相关的信息。这意味着,每当我需要处理一个新的JSON负载(可能会重用枚举)时,我都必须进入枚举文件并添加额外的信息。这是
enum
和需要处理的选项之间的权衡。当然,您可以使用
contains
甚至创建
RegExp
来匹配尽可能多的不同选项,而不是严格匹配(
equals
equalsIgnoreCase
)。您肯定应该有一个
enum
来表示不同的语言。如果不想一直更改枚举并重新编译,可以将反序列化推迟到另一个类,在该类中可以从属性文件加载所有可能的值。