使用没有 JsonSubTypes 的 jackson 将接口反序列化为特定类型

Deserialize interface to specific type with jackson without JsonSubTypes

我有一个项目 A,我有一个这样的界面:

interface MyInterface extends Serializable { }

在另一个项目 B 中,我有一个 class 实现了该接口:

@Data
class MyClass implements MyInterface {
    private String someProp;
}

现在我想告诉jackson,我想将MyInterface的所有出现反序列化为MyClass。我知道通常可以使用 JsonSubTypes 但在这种情况下项目 A 不知道项目 B.

有没有办法获取类型的默认反序列化器?然后我可以做这样的事情:

SimpleModule module = new SimpleModule();
module.addDeserializer(MyInterface.class, DefaultDeserializerForMyClass);

我知道我可以编写完全相同的自定义反序列化器,但是有更简单的方法吗?

您可以在 MyClass 上添加 @JsonDeserialize 并使用 ObjectMapper.addMixIn()MyInterface 作为目标。

public ObjectMapper addMixIn(Class target, Class mixinSource)

Method to use for adding mix-in annotations to use for augmenting specified class or interface. All annotations from mixinSource are taken to override annotations that target (or its supertypes) has.

target - Class (or interface) whose annotations to effectively override mixinSource - Class (or interface) whose annotations are to be "added" to target's annotations, overriding as necessary

例如:

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

@JsonDeserialize(as = MyClass.class)
class MyClass implements MyInterface
{
        private String someProp;

        /* getters and setters */
}

@Bean
public ObjectMapper objectMapper()
{
        ObjectMapper om = new ObjectMapper();
        om.addMixIn(MyInterface.class, MyClass.class);
        return om;
}

@PostMapping
public String foo(@RequestBody MyInterface bar)
{
        if (bar instanceof MyClass) {
                MyClass baz = (MyClass)bar;
                System.out.println(baz.getSomeProp());
                return "world"
        }
        return "goodbye"
}

$ curl -X POST -d '{"someProp": "hello"}' -H "content-type: application/json" localhost:8080
world

并且服务器正确打印:

hello