首页 > 解决方案 > 带有 JsonTypeInfo 的 Spring Boot Jackson defaultImpl

问题描述

我正在尝试处理在 Spring Boot 应用程序中的 REST API 请求期间出现的所有类型的 Jackson 异常。如果某些东西无法序列化,JsonMappingException则抛出。我处理此异常,构建无法序列化的字段路径(使用exception.getPath)并返回此信息。

现在,我有一些实现相同接口(多态性)的类,并且必须在请求期间使用它们。这意味着我还将它们公开给 REST API,并且可以包含在请求/响应正文中。这是界面:

@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.EXISTING_PROPERTY,
    property = "service",
    defaultImpl = DefaultNotificatorPresentation.class,
    visible = true
)
@JsonSubTypes({
    @JsonSubTypes.Type(value = EmailNotificatorPresentation.class, name = "email")
})
public interface NotificatorPresentation {
    String getService();
}

基本上,有不同类型的通知器,它们都有不同的服务(电子邮件、短信等)。此属性用于@JsonTypeInfo. 在我开始测试JsonMappingExceptionJSON 子类型是否正确抛出之前,一切都按预期工作。

JsonMappingException为所有属性(例如,格式错误)和InvalidTypeIdException服务不是任何可用类型(目前只有电子邮件)抛出。我想告诉用户服务属性的可用选项(当给出字符串但与可用类型不匹配时 - 电子邮件、短信等),并且在没有提供字符串时它格式错误(例如对象或数组) .

我想出了一个使用@JsonTypeInfo并使用带有自定义验证注释的自定义类并处理它defaultImpl的解决方案。ConstraintValidator

public class DefaultNotificatorPresentation implements NotificatorPresentation {
    // implementation of getService() and validation annotation
}

注释有一个默认消息 - available services are only email, sms。这样,每次创建默认实现时(总是在用户提供无效服务时)都会出现验证错误。service例如,当json 请求中的属性为字符串类型时此方法有效"not found service"

但是当object( { "example": true }) 设置为服务属性时,defaultImpl该类被创建了两次。第一个实例是属性服务"{" (的第一个字符{ "example": true }。第二个服务只是null。这会创建 2 个验证异常,但必须抛出JsonMappingException.

您对如何解决这个问题有任何想法吗?我什至可以使用一种完全不同的方法来处理杰克逊多态性。

标签: javajsonspringspring-bootjackson

解决方案


推荐阅读