当前位置: 首页 > 知识库问答 >
问题:

ObjectMapper无法处理具有旧枚举(类)的映射对象

罗昕
2023-03-14

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

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

在旧系统中,有如下枚举:

public final class LegacyEnum extends LegacyEnumSuperclass {

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

我将这些“枚举”的值作为html" target="_blank">字符串接收,我将其转换为旧的枚举值(自定义反序列化器),并在自定义类中设置它们(我需要它,因为我使用的是jackson注释,并且我没有修改旧代码的访问权或权限),这部分工作得很好。当我尝试将自定义对象映射到具有

objectMapper.convertValue(myCustomObject, LegacyObjectContainingEnums.class); 

我得到一个例外:

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类有一个私有构造函数,而LegacyEnumSuperclass有一个类似的受保护构造函数,因此我无法访问它们(ObjectMapper也不能)。我曾尝试实现一个自定义转换器,它将跳过ObjectMapper映射的“创建新对象”部分,并且我还尝试重用我的自定义反序列化程序。我遇到了许多问题,但没有取得成功。

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

有什么想法吗?

共有1个答案

况明贤
2023-03-14

我通过使用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));
}

值类型。getRawClass()返回LegacyEnum。类,这样我就可以对继承LegacyEnumSuperclass类的所有“枚举”使用一个反序列化器。getEnum是一个来自遗留代码的自定义方法。

在ObjectMapper Spring配置中注册MixIn:

@Configuration
public class ObjectMapperConfig {

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

这样,我可以在Controller方法中使用LegacyClass作为参数。谢谢线索。

 类似资料:
  • 问题内容: 我需要预先将未实现接口的枚举映射到现有数据库,该数据库使用将该枚举存储在与所有者类相同的表中。 在这种情况下应如何处理映射?持久化到数据库不会改变,因为实现该接口的所有枚举都将具有不同的值,但是我不确定应如何从数据库中检索对象(我是否需要自定义映射器,它将尝试实例化一个使用指定的enum类进行枚举吗?Hibernate本身是否支持此功能?)。 问题答案: 可以创建一个自定义(例如thi

  • 问题内容: Hibernate提供的注释支持使用或的两种类型的映射。当我们使用映射时,它使用的“名称” 而不是Enum的表示形式。在数据库列仅包含一个字符的情况下,这是一个问题。例如,我有以下枚举: 当我坚持枚举使用,即hibernate尝试在数据库中存储的值是开放的。但是,我的数据库列仅包含一个字符,因此会引发异常。 克服这个问题的一个办法是改变枚举类型持有单个字符(如,代替,)。但是,这降低了

  • 枚举类(“新的枚举”/“强类型的枚举”)主要用来解决传统的C++枚举的三个问题: 传统C++枚举会被隐式转换为int,这在那些不应被转换为int的情况下可能导致错误 传统C++枚举的每一枚举值在其作用域范围内都是可见的,容易导致名称冲突(同名冲突) 不可以指定枚举的底层数据类型,这可能会导致代码不容易理解、兼容性问题以及不可以进行前向声明 枚举类(enum)(“强类型枚举”)是强类型的,并且具有类

  • 在我的表中,我希望有指向MyEnumCode表的字段。 使用currenlty同时支持EnumType.Ordinal和EnumType.String,我想这不是一个好主意。 还有一个问题。如何使用Java类数据填写表?你会怎么做?最好的方法。 这里当然有弊端。但目前我看不出更好的方法。请不要提供EnumType.Ordinal和EnumType.String的备选项。我不想在这里写它的用法可能存

  • 问题内容: 我需要预先将没有实现接口的枚举映射到现有数据库,该数据库使用将该枚举存储在与所有者类相同的表中。 在这种情况下应如何处理映射?持久化到数据库不会改变,因为实现该接口的所有枚举都将具有不同的值,但是我不确定应如何从数据库中检索对象(我是否需要自定义映射器,它将尝试实例化一个使用指定的enum类进行枚举吗?Hibernate是否本身支持此功能?)。 问题答案: 可以创建一个自定义(例如th