默认情况下,使用 Jackson 解析为子类

2022-09-03 04:21:04

我有一个名为 Product 的类和一些扩展它的子类。现在在我的注释中,我有很多类型,如下所示:

@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.WRAPPER_OBJECT)
@JsonSubTypes({@Type(value=RoomProduct.class, name="RoomProduct"),
           @Type(value=GroundProduct.class, name="GroundProduct"),
           })

然后是我的产品类的定义。我想做的是,如果 Jackson 无法检测到该字段不符合这些结构中的任何一个,则返回一个

未知产品

我如何使用杰克逊@Type注释执行此操作?它应该是在名称中放置空白或一些我并不真正知道的值的标志(我尝试过创建扩展产品的UnknownProduct,并且在名称值中不添加任何内容,但没有成功。


答案 1

@JsonTypeInfo有一个指定默认实现类的选项,但经过一些调试后,我发现包装对象的“defaultImpl”已损坏。配置:

@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include= JsonTypeInfo.As.WRAPPER_OBJECT, defaultImpl = UnknownProduct.class)

Jackson implementation (AsWrapperTypeDeserializer):

public AsWrapperTypeDeserializer(JavaType bt, TypeIdResolver idRes,
        String typePropertyName, boolean typeIdVisible, Class<?> defaultImpl)
{
    super(bt, idRes, typePropertyName, typeIdVisible, null);
}

请注意,“defaultImpl”已传递,但会被忽略,并且不会使用配置的默认类。我没有在杰克逊的Jira中找到这个问题的记录票证。

这仅对WRAPPER_OBJECT来说是一个问题,默认Impl对于其他格式工作正常。但它会改变JSON格式。如果您可以更改它 - 则可以使用EXTERNAL_PROPERTY例如默认实现:

@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include= JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "type", defaultImpl = UnknownProduct.class)

另一个解决方案:如果您必须使用WRAPPER_OBJECT则可以将Jackson配置为在发现未知子类型时不会失败:

objectMapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false);

这与您要求的不完全相同,但在这种情况下,您的产品将为空。也许您可以将 null 视为未知产品。

更新我提交了一个杰克逊错误:https://github.com/FasterXML/jackson-databind/issues/656

更新此票证已在 2.3 和 2.4 jackson 中得到解决,希望很快当 jar 将重新安装到 maven 存储库或新版本中时,您应该能够使用它。


答案 2

推荐