objectmapper无法处理具有旧枚举(类)的Map对象

rslzwgfq  于 2021-07-09  发布在  Java
关注(0)|答案(1)|浏览(518)

我在为一些遗留代码构建rest体系结构时遇到了一个问题。jackson objectmapper无法将我的自定义对象Map到遗留对象,因为“enum”实际上是带有静态final字段的类。
我尝试实现自定义转换器/反序列化程序,但没有成功
在旧系统中,有如下枚举:

public final class LegacyEnum extends LegacyEnumSuperclass {

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

我以字符串的形式接收这些“enum”的值,将其转换为遗留enum值(自定义反序列化程序)并在自定义类中设置它们(我需要它,因为我使用的是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也不能访问)。我尝试过实现一个自定义转换器,它将跳过objectmapperMap的“createnewobject”部分,并且我还尝试重用我的自定义反序列化程序。我遇到了多个问题,但都没有成功。
最恼人的是,当我使用modelmapper库时,它就像一个符咒(它可能只是在遗留对象中设置了一个值,不需要像objectmapper一样创建新的legacyenum示例!)但我正在尝试在不添加新依赖项的情况下解决这个问题。
有什么想法吗?

6qqygrtg

6qqygrtg1#

我通过使用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类的所有“enum”使用一个反序列化程序。getenum是一个自定义方法,来自遗留代码。
在objectmapper spring配置中注册mixin:

@Configuration
public class ObjectMapperConfig {

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

这样我就可以在控制器方法中使用legacyclass作为参数。谢谢你提供线索。

相关问题