Java 一种将枚举与JSON有效负载中绑定的值解耦的干净方法,以便它们更易于重用?
我从其他答案中了解到,要序列化和反序列化Jackson中不同基础值的枚举,我必须在enum类中执行以下操作: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
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可以在序列化和反序列化期间将enumLanguageType.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
来表示不同的语言。如果不想一直更改枚举并重新编译,可以将反序列化推迟到另一个类,在该类中可以从属性文件加载所有可能的值。