[英]How do you modify default enum (de)serialization for non-annotated enums but retain standard behavior (@JsonProperty/@JsonValue/...) in Jackson?
Currently jackson (uncustomized) serializes enums like this:目前 jackson (uncustomized) 像这样序列化枚举:
@JsonProperty
or @JsonValue
, they are used to derive serialized name@JsonProperty
或@JsonValue
,它们用于派生序列化名称toString()
might be used (depending on the mapper settings), or .name()
is called by defaulttoString()
(取决于映射器设置),或默认调用.name()
For deserialization, it's like this:对于反序列化,是这样的:
@JsonProperty
, @JsonValue
or @JsonCreator
, they influence deserialization@JsonProperty
、 @JsonValue
或@JsonCreator
,它们会影响反序列化 I'd like to keep items 1 in both cases (ie still support all 3 annotations, or more if I miss something), but modify behavior for the 'default case': for example, always serialize enums as .name().toLowercase()
if no annotations are present.我想在这两种情况下都保留第 1 项(即仍然支持所有 3 个注释,如果我遗漏了一些注释,或者更多),但修改“默认情况”的行为:例如,始终将枚举序列化为
.name().toLowercase()
如果没有注释。
I could use addSerializer()
, addDeserializer()
or (de)serializer modification mechanisms, but none of these allow easy and elegant solution.我可以使用
addSerializer()
、 addDeserializer()
或 (de)serializer 修改机制,但这些都不允许简单而优雅的解决方案。 All I could invent is either copy/paste tons of code from jackson (which is ugly and fragile), or, using modification mechanism, introspect the enum class emulating jackson's involved logic to identify cases when the 'default' logic would apply and then use my 'to-lower-case' strategy.我所能发明的只是从 jackson 复制/粘贴大量代码(这是丑陋和脆弱的),或者,使用修改机制,内省模拟 jackson 涉及的逻辑的枚举类,以识别“默认”逻辑何时适用的情况,然后使用我的“小写”策略。
Is there a better way to modify the 'default' serialization strategy while still leaving all the 'non-default' cases?有没有更好的方法来修改“默认”序列化策略,同时仍然保留所有“非默认”情况?
You can insert a new AnnotationIntrospector whose findEnumValues
method changes the enum name.您可以插入一个新的AnnotationIntrospector,其
findEnumValues
方法会更改枚举名称。 The EnumRenamingModule
from the therapi-json-rpc project uses this technique.该
EnumRenamingModule
从therapi-JSON-RPC项目使用了这种技术。 (Disclaimer: this is my pet project.) Here's the code, copied from the GitHub repo: (免责声明:这是我的宠物项目。)这是从 GitHub 存储库复制的代码:
package com.github.therapi.jackson.enums;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.introspect.NopAnnotationIntrospector;
import com.fasterxml.jackson.databind.module.SimpleModule;
/**
* Customizes the way Jackson serializes enums.
*/
public abstract class EnumRenamingModule extends SimpleModule {
private boolean overrideExistingNames;
public EnumRenamingModule() {
super("therapi-enum-renaming");
}
/**
* Configures the module to clobber any enum names set by
* a previous annotation introspector.
*/
public EnumRenamingModule overrideExistingNames() {
this.overrideExistingNames = true;
return this;
}
@Override
public void setupModule(Module.SetupContext context) {
super.setupModule(context);
context.insertAnnotationIntrospector(new EnumNamingAnnotationIntrospector());
}
private class EnumNamingAnnotationIntrospector extends NopAnnotationIntrospector {
public String[] findEnumValues(Class<?> enumType, Enum<?>[] enumValues, String[] names) {
for (int i = 0; i < enumValues.length; i++) {
if (names[i] == null || overrideExistingNames) {
names[i] = EnumRenamingModule.this.getName(enumValues[i]);
}
}
return names;
}
}
/**
* @param value the enum value to inspect
* @return the JSON name for the enum value, or {@code null} to delegate to the next introspector
*/
protected abstract String getName(Enum<?> value);
}
Create a subclass to do the transformation you want:创建一个子类来做你想要的转换:
public class LowerCaseEnumModule extends EnumRenamingModule {
@Override protected String getName(Enum<?> value) {
return value.name().toLowerCase(Locale.ROOT);
}
}
And register it with your ObjectMapper:并使用您的 ObjectMapper 注册它:
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new LowerCaseEnumModule());
Annotation @JsonCreator
is used to deserialize (it's a static factory).注解
@JsonCreator
用于反序列化(它是一个静态工厂)。
Annotation @JsonValue
is used to serialize.注解
@JsonValue
用于序列化。
The given example does work for me :给定的例子对我有用:
class MyException extends RuntimeException {}
enum MyEnum {
TEST;
private final String value;
private MyEnum() {
this.value = this.name().toLowerCase();
}
@JsonValue
public final String value() {
return this.value;
}
@JsonCreator
public static MyEnum forValue(String value) {
return Arrays.stream(MyEnum.values()).filter(myEnum -> myEnum.value.equals(value)).findFirst().orElseThrow(MyException::new);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.