我在为一些遗留代码构建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实例!)但我正试图在不添加新依赖项的情况下解决这个问题。
有什么想法吗?
我通过使用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的备选项。我不想在这里写它的用法可能存
我试图将所有映射到相同的DTO类,我希望避免为每个类型声明一个方法,或者为每个枚举字段使用。 然后在我的其他地图上 但MapStruct仍在为每种枚举类型生成一种新的映射方法,而且实现方式不符合我的需要。 有没有办法用MapStruct做到这一点?还是太神奇了D