简体   繁体   English

您如何修改未注释枚举的默认枚举(反)序列化,但在 Jackson 中保留标准行为(@JsonProperty/@JsonValue/...)?

[英]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) 像这样序列化枚举:

  1. If there is @JsonProperty or @JsonValue , they are used to derive serialized name如果有@JsonProperty@JsonValue ,它们用于派生序列化名称
  2. Otherwise, standard serialization is carried out: index or toString() might be used (depending on the mapper settings), or .name() is called by default否则,执行标准序列化:可能使用 index 或toString() (取决于映射器设置),或默认调用.name()

For deserialization, it's like this:对于反序列化,是这样的:

  1. If there is @JsonProperty , @JsonValue or @JsonCreator , they influence deserialization如果有@JsonProperty@JsonValue@JsonCreator ,它们会影响反序列化
  2. Otherwise, standard deserialization is used which mirrors serialization.否则,使用标准反序列化来反映序列化。

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.EnumRenamingModuletherapi-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.

相关问题 Jackson序列化和@JsonValue:返回默认行为 - Jackson serialization and @JsonValue : back to the default behavior 如何在 Jaxb 中默认将非注释字段映射到属性 - How to map non-annotated fields to attributes by default in Jaxb 泽西岛无注释提供商 - Jersey non-annotated Provider 如何使用Morphia映射未注释的pojo? - How can I use Morphia to map a non-annotated pojo? 枚举Jackson的@JsonProperty - Enums for Jackson's @JsonProperty 如何检索特定类中存在的带注释和无注释的方法 - how to retrieve annotated and non-annotated methods present inside a perticular class 在IntelliJ Java的代码样式中,我们如何将其设置为在带注释的字段之间要求空行,而在非带注释的字段之间不要求空行 - in IntelliJ Java's Code Style how do we set it up to require blank line between annotated fields and no blank line between non-annotated fields AspectJ:如何选择给定类的子类的非注释方法的执行? - AspectJ: How to pick the execution of non-annotated methods of subclasses of a given class? JAXB编组非注释对象列表的问题 - Problems with JAXB marshalling lists of non-annotated objects 未注释字段的Hibernate org.hibernate.MappingException - Hibernate org.hibernate.MappingException for non-annotated field
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM