杰克逊对多个类型的反序列化

2022-09-01 19:07:10

我有一个名为抽象类的抽象类,然后是它的两个实现,以及.我遇到的问题是,当我将 rest 终结点调用到数据库中时,理想情况下,我希望它类似于将实例传递到 REST 终结点的位置。如果不是抽象的,有多个实现就好了,但是因为我有2个,所以我得到了一个错误。InstanceUserInstanceHardwareInstance@POST.../rest/soexample/instance/createInstanceJackson.databind

“问题:抽象类型要么需要映射到具体类型,要么具有自定义反序列化程序,要么使用其他类型信息进行实例化”

在查找了这个问题的解决方案之后,我找到了一个SO答案,说我可以使用这样的东西:

@JsonDeserialize(as=UserInstance.class)

但是,如果抽象类有一个实现,这似乎只是有用的。假设我不能调用它两次,因为它无法决定它将是哪种类型的实例。

所以我想知道处理这种情况的最佳方法是什么?是否应创建不同的终结点?喜欢:

.../rest/soexample/userinstance/create & .../rest/soexample/hardwareinstance/create

我不太确定,因为我是一个菜鸟@REST相关的东西,尽管积极尝试学习。谢谢!


答案 1

以下是我在你同样的案例中所做的:

@JsonDeserialize(using = InstanceDeserializer.class)
public abstract class Instance {
    //.. methods
}

@JsonDeserialize(as = UserInstance.class)
public class UserInstance extends Instance {
    //.. methods
}

@JsonDeserialize(as = HardwareInstance.class)
public class HardwareInstance extends Instance {
    //.. methods
}

public class InstanceDeserializer extends JsonDeserializer<Instance> {
    @Override
    public Instance deserialize(JsonParser jp,  DeserializationContext ctxt) throws IOException, JsonProcessingException {
        ObjectMapper mapper = (ObjectMapper) jp.getCodec();
        ObjectNode root = (ObjectNode) mapper.readTree(jp);
        Class<? extends Instance> instanceClass = null;
        if(checkConditionsForUserInstance()) {
            instanceClass = UserInstance.class;
        } else { 
            instanceClass = HardwareInstance.class;
        }   
        if (instanceClass == null){
            return null;
        }
        return mapper.readValue(root, instanceClass );
    }
}

您可以对 进行批注,以指示要用于反序列化抽象类的类。然后,您需要指示每个子类将自行反序列化,否则它们将使用父类反序列化程序,您将获得.Instance@JsonDeserialize(using = InstanceDeserializer.class)asStackOverflowError

最后,在内部,您将要反序列化的逻辑放入一个或另一个子类中(例如)。InstanceDeserializercheckConditionsForUserInstance()


答案 2