java - ObjectMapper 无法处理具有遗留枚举(类)的映射对象

标签 java enums legacy objectmapper

我在为一些遗留代码构建 REST 架构时遇到了问题。 Jackson ObjectMapper 无法将我的自定义对象映射到遗留对象,因为“枚举”实际上是具有静态最终字段的类。

我尝试实现自定义转换器/反序列化器但没有成功

在遗留系统中有如下所示的枚举:

public final class LegacyEnum extends LegacyEnumSuperclass {

    public static final LegacyEnum VALUE = new LegacyEnum("1");

我正在接收这些“枚举”的值作为字符串,我将其转换为遗留枚举值(自定义反序列化器)并将它们设置在我的自定义类中(我需要它,因为我正在使用 jackson 注释,而且我没有访问或修改遗留代码的权限)并且这部分工作得很好。当我尝试使用

将我的自定义对象映射到遗留对象时
objectMapper.convertValue(myCustomObject, LegacyObjectContainingEnums.class); 

我得到一个异常(exception):

Can not construct instance of LegacyEnum: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?)

LegacyEnum 类有一个私有(private)构造函数,LegacyEnumSuperclass 有一个类似的 protected 构造函数,所以我无法访问它们(ObjectMapper 也不能)。我已经尝试实现一个自定义转换器,它将跳过 ObjectMapper 映射的“创建新对象”部分,并且我还尝试重用我的自定义反序列化器。我遇到了多个问题,但没有成功。

最烦人的部分是,当我使用 ModelMapper 库时,它就像一个魅力(它可能只是在遗留对象中设置一个值,不需要像 ObjectMapper 这样创建新的 LegacyEnum 实例!)但我正在尝试解决在不添加新依赖项的情况下解决这个问题。

有什么想法吗?

最佳答案

我通过使用 MixIn 和自定义解串器解决了这个问题,如下所示:

public abstract class LegacyClassMixIn 
    @JsonDeserialize(using = LegacyEnumDeserializer.class)
    abstract LegacyEnum getLegacyEnum();

反序列化器:

public class LegacyEnumDeserializer extends JsonDeserializer<LegacyEnumSuperclass> implements ContextualDeserializer {

private JavaType valueType;

@Override
public JsonDeserializer createContextual(DeserializationContext context, BeanProperty property) {
    JavaType wrapperType = property.getType();
    LegacyEnumDeserializer deserializer = new LegacyEnumDeserializer();
    deserializer.valueType = wrapperType;

    return deserializer;
}

@Override
public LegacyEnumSuperclass deserialize(JsonParser parser, DeserializationContext context) throws IOException {
    return LegacyEnumSuperclass.getEnum(valueType.getRawClass(), parser.readValueAs(String.class));
}

valueType.getRawClass() 返回 LegacyEnum.class,这样我就可以对继承 LegacyEnumSuperclass 类的所有“枚举”使用一个解串器。 getEnum 是来自遗留代码的自定义方法。

在 ObjectMapper Spring 配置中注册 MixIn:

@Configuration
public class ObjectMapperConfig {

    public ObjectMapperConfig(ObjectMapper objectMapper) {
        objectMapper.addMixIn(LegacyClass.class, LegacyClassMixIn.class);
    }
}

这样我就可以将 LegacyClass 用作 Controller 方法中的参数。 感谢您提供线索。

关于java - ObjectMapper 无法处理具有遗留枚举(类)的映射对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54512441/

相关文章:

java - 枚举上的调用方法

ruby-on-rails - 带有遗留只读数据库的 Factory Girl

android - 为什么从 API 18 开始,API 演示被视为 "legacy"?

java - Spring MVC DispatcherServlet 错误

java - JDBC 连接池测试查询 "SELECT 1"未捕获 AWS RDS 写入器/读取器故障转移

java - 匹配表达式并替换

linux - g77 版本 3.2 使用选项 -finit-local-zero 创建大目标文件

java - 一个月中倒数第二个星期的 Cron 表达式

java - 序列化/反序列化公共(public)枚举的简单方法?

java - 如何在枚举中不存在的 selectOne 中显示值?