【问题标题】:Swagger API consuming json with json validationSwagger API 使用带有 json 验证的 json
【发布时间】:2016-03-05 08:11:55
【问题描述】:

我正在使用 Swagger 生成一个 Restful API:

@POST
@Consumes({ "application/json" })
@Produces({ "application/json" })
@io.swagger.annotations.ApiOperation(value = "Create a task", notes = "", response = Tasks.class)
@io.swagger.annotations.ApiResponses(value = { 
    @io.swagger.annotations.ApiResponse(code = 200, message = "created task", response = Tasks.class),
    @io.swagger.annotations.ApiResponse(code = 404, message = "task not found", response = Tasks.class),
    @io.swagger.annotations.ApiResponse(code = 200, message = "unexpected error", response = Tasks.class) })
public Response createTask(@ApiParam(value = "The task to create" ,required=true ) NewTask newTask)
throws NotFoundException {
    return delegate.createTask(newTask);
}

此 API 接受 json 字符串并从中生成 java 对象。除了一个例外,这运行得很好: API 接受任何正确形成的 json 字符串,但忽略 json 的内容,这意味着我得到了一个使用默认值创建的对象。

所以我的问题是: 如何在生成实际的 java 对象之前验证传入的 jsonstring(针对 json 模式)?

【问题讨论】:

  • 如何对模式进行验证?例如,您可以将 JSON 作为字符串接收,对其进行验证,然后使用 Jackson 从它创建一个对象。但是,既然您正在执行验证,您是否考虑过Bean Validation
  • 问题是,我必须更改 API 以在方法参数 afaik 中接收 json 字符串而不是 public Response createTask(String jsonTask) 之类的对象,但如果可能的话,我更愿意将对象放在那里。

标签: java json rest swagger


【解决方案1】:

swagger-request-validator 有多个适用于各种框架的适配器,例如:Spring Web MVC

它能够针对 Swagger / OpenAPI 2 或 OpenAPI 3 方案验证请求和/或响应。

请参阅此处:Validating JSON messages against Swagger definition in Java 以获得更详细的答案。

【讨论】:

    【解决方案2】:

    由于您不希望在您的方法中接收 JSON 字符串并且Bean Validation 不是您的验证选项,您可以尝试使用MessageBodyWriter<T>

    JAX-RS 使用MessageBodyWriter<T>s 来解析传入的请求。由于您想要一些非常具体的东西,请考虑writing your own MessageBodyWriter<T>

    请看下面的例子:

    @Provider
    @Produces("application/json")
    public class CustomMessageBodyWriter implements MessageBodyWriter<Object> {
    
        @Override
        public boolean isWriteable(Class<?> type, Type genericType,
                                   Annotation[] annotations, MediaType mediaType) {
            return true;
        }
    
        @Override
        public long getSize(MyBean myBean, Class<?> type, Type genericType,
                            Annotation[] annotations, MediaType mediaType) {
    
            // Deprecated by JAX-RS 2.0
            return 0;
        }
    
        @Override
        public void writeTo(Object object, Class<?> type, Type genericType,
                            Annotation[] annotations, MediaType mediaType,
                            MultivaluedMap<String, Object> httpHeaders,
                            OutputStream entityStream) throws IOException {
    
            // Read the entityStream
            // Perform the validation against your schema
            // Write to the object
        }
    }
    

    @Provider 注释使 JAX-RS 运行时在提供程序扫描阶段自动发现该类。

    【讨论】:

    • 一个问题:我使用的是 Swagger,它自带了 MessageBodyWriter。 link 我需要更改招摇的来源吗?还是有另一种方法可以强制使用我自己的实现(无需反射)?
    • @Gobliins 用 @Providerregistering it to your Applicationor ResourceConfig class 注释您的 MessageBodyWriter 应该足以让 Jersey/JAX-RS 识别它。
    • Err.. 我不需要其他方式(DeSerializer)吗?因为我想在将传入的 json 映射到模型之前验证它,而不是在 json 流中写入模型?
    • @Gobliins Jersey/JAX-RS 已经为 JSON 提供了 MessageBodyReader&lt;T&gt;。如果提供的不符合您的需要,您可以自己编写。
    猜你喜欢
    • 2017-01-09
    • 1970-01-01
    • 1970-01-01
    • 2019-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-13
    • 1970-01-01
    相关资源
    最近更新 更多