Как опустить пустое поле из Swagger / OpenAPI в ResponseEntity? - PullRequest
2 голосов
/ 18 февраля 2020

Я пытаюсь опустить пустые значения в моем 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...
}

Когда NULLABLE_OBJECT равно null Я ожидаю, что поле будет опущено в ответе следующим образом:

{
  "firstName": "John",
  "lastName": "Doe"
}

Но я получаю либо эти ответы, в зависимости от того, что я пробовал до сих пор:

{
  "firstName": "John",
  "lastName": "Doe",
  "testField": null
}

или

{
   "firstName": "John",
   "lastName": "Doe",
   "testField": {"present":false}
}

Я генерирую свои объекты запроса / ответа (CreateFooResponseV10 и CreateFooRequestV10) с использованием openapi-генератора

Вот мой отредактированный файл 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
          }
        }
      }
    }
  }
}

Как вы можете видеть на обоих запрос и ответ testField не требуется и может быть обнуляемым. Поэтому, когда testField равен null, он должен быть скрыт от ответа, но когда он содержит некоторую дату, он должен быть показан, конечно.

Я попытался переопределить компонент ObjectMapper Джексона, как объяснено в этого ответа . Не сработало
Я пытался добавить 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

Ответы [ 2 ]

0 голосов
/ 18 февраля 2020

Попробуйте зарегистрировать следующий боб в своем весеннем контексте. Он должен переопределить бин по умолчанию

@Bean
public HttpMessageConverters httpMessageConverters() {
    ObjectMapper mapper = new ObjectMapper();
    mapper.setSerializationInclusion(Include.NON_NULL)
    return new HttpMessageConverters(
            new MappingJackson2HttpMessageConverter(mapper));
}
0 голосов
/ 18 февраля 2020

Попробуйте этот код. Я проверил, и это работает.

@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;
    }

}

Json ответ:

{"firstName":"John","lastName":"Doe"}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...