如何从 ResponseEntity 中的 Swagger/OpenAPI 中省略空字段?

Edw*_*ard 8 spring json swagger openapi openapi-generator

我试图在我的 ResponseEntity 中省略空值。

我的控制器看起来像这样:

@RestController
public class FooController {

    //fields
    //constructor

    @PostMapping
    public ResponseEntity<CreateFooResponseV10> createFoo(@Valid @RequestBody CreateFooRequestV10 foo, HttpServletRequest request) {
        //some minor logic
        return new ResponseEntity<>(aFooResponseV10Builder()
                .withFirstName(foo.getFirstName())
                .withLastName(foo.getLastName())
                .withTestField(NULLABLE_OBJECT)
                .build(), ...);
    //I generated the builders from the output classes openapi-generator provided
    }
    // more stuff...
}
Run Code Online (Sandbox Code Playgroud)

When NULLABLE_OBJECTis equal tonull我希望从响应中省略该字段,如下所示:

{
  "firstName": "John",
  "lastName": "Doe"
}
Run Code Online (Sandbox Code Playgroud)

但我要么得到这些回应,这取决于我到目前为止的尝试:

{
  "firstName": "John",
  "lastName": "Doe",
  "testField": null
}
Run Code Online (Sandbox Code Playgroud)

或者

{
   "firstName": "John",
   "lastName": "Doe",
   "testField": {"present":false}
}
Run Code Online (Sandbox Code Playgroud)

我使用openapi-generator生成我的请求/响应对象(CreateFooResponseV10和CreateFooRequestV10)

这是我的编辑api.json文件:

{
  "openapi": "3.0.1",
  "info": { ... },
  "servers": [ ... ],
  "paths": {
    "/foo": {
      "post": {
        ...
        "requestBody": {
          "description": "Foo to be created",
          "content": {
            "application/foo+json;version=1.0": {
              "schema": {
                "$ref": "#/components/schemas/CreateFooRequest_V1_0"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Foo is successfully created",
            "headers": { ... },
            "content": {
              "application/foo+json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateFooResponse_V1_0"
                }
              }
            }
          },
          ...
        }
      }
    }
  },
  "components": {
    "schemas": {
      "CreateFooRequest_V1_0": {
        "required": [
          "firstName",
          "lastName"
        ],
        "type": "object",
        "properties": {
          "firstName": { ... },
          "lastName": { ... },
          "testField": {
            "description": "...",
            "type": "string",
            "nullable": true
          }
        }
      },
      "CreateFooResponse_V1_0": {
        "required": [
          "firstName",
          "lastName"
        ],
        "type": "object",
        "properties": {
          "firstName": { ... },
          "lastName": { ... },
          "testField": {
            "description": "...",
            "type": "string",
            "nullable": true
          }
        }
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

正如您在请求和响应中所见,testField不需要并且可以为空。因此,当 testField 是null它时,它应该从响应中隐藏,但是当它包含某个日期时,它当然应该显示出来。

我已经尝试覆盖 jackson 的 ObjectMapper bean,如本答案中所述。没用。
我试过添加spring.jackson.default-property-inclusion=non_null到application.properties. 没用。

我认为应该在@JsonIgnore上面添加testField生成的类,但我不知道这是否需要手动完成(对于每个架构组件,对于生成的内容可能需要大量手动工作),或者如果这可以在插件中的某处配置。

提前致谢。


额外信息
OpenAPI 3.0.1
Maven 3.6.3
Java 11.0.2
jackson-databind-nullable 0.2.1
openapi-generator-maven-plugin 4.2.2

小智 8

您可以使用 OpenApi 生成器生成带有附加类注释的模型类。只需要在你的 Maven 插件中包含这个:

<configOptions>
   <additionalModelTypeAnnotations>
@com.fasterxml.jackson.annotation.JsonInclude(com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL)
   </additionalModelTypeAnnotations>
<configOptions>
Run Code Online (Sandbox Code Playgroud)

在这里查看其他配置选项: https ://openapi-generator.tech/docs/generators/spring/


Jus*_*ice 6

您可以在 application.properties

spring.jackson.default-property-inclusion = NON_NULL
Run Code Online (Sandbox Code Playgroud)

请参阅自定义 Jackson ObjectMapper


Max*_*pov 5

尝试在您的 spring 上下文中注册以下 bean。它应该覆盖默认的bean

@Bean
public HttpMessageConverters httpMessageConverters() {
    ObjectMapper mapper = new ObjectMapper();
    mapper.setSerializationInclusion(Include.NON_NULL)
    return new HttpMessageConverters(
            new MappingJackson2HttpMessageConverter(mapper));
}
Run Code Online (Sandbox Code Playgroud)


Kev*_* Le -3

试试这个代码。我测试过并且有效。

@RestController
@RequestMapping("/testws")
public class TestWS {
    @RequestMapping(value = "test", method = { RequestMethod.POST,
            RequestMethod.GET }, produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public ResponseEntity<TestBean> test(@Context HttpServletRequest request) {
        TestBean testBean = new TestBean("John", "Doe", null);
        return ResponseEntity.ok()
                .body(testBean);
    }
}

@JsonInclude(Include.NON_NULL)
class TestBean {
    private String firstName;
    private String lastName;
    private String testField;

    public TestBean() {

    }

    public TestBean(String firstName, String lastName, String testField) {
        super();
        this.firstName = firstName;
        this.lastName = lastName;
        this.testField = testField;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getTestField() {
        return testField;
    }

    public void setTestField(String testField) {
        this.testField = testField;
    }

}
Run Code Online (Sandbox Code Playgroud)

杰森响应:

{"firstName":"John","lastName":"Doe"}
Run Code Online (Sandbox Code Playgroud)