Swagger oneOf типа: Джексон пытается создать экземпляр интерфейса вместо реализации? - PullRequest
0 голосов
/ 28 января 2020

Я использую функцию oneOf, чтобы определить несколько возможных схем, которые могут go войти в свойство тела запроса моей службы. В сгенерированном клиентском коде Java реализации Java этих схем реализуют интерфейс, но когда я отправляю запрос через него, Джексон пытается создать экземпляр интерфейса вместо конкретного класса.

Версия Swagger-codegen

<groupId>io.swagger.codegen.v3</groupId>
<artifactId>swagger-codegen-maven-plugin</artifactId>
<version>3.0.14</version>

Содержимое файла декларации Swagger

schemas:
    TestRequest:
      description: 
        Test request
      type:
        object
      required:
        - criteria
      properties:
        criteria:
          oneOf:
           - $ref: '#/components/schemas/CriteriaA'
           - $ref: '#/components/schemas/CriteriaB'
    ...
    CriteriaA:
      description: Criteria A
      type: object
      required:
        - type
        - query
      properties:
        type: 
          description: A description
          type: string
          enum:
           - CriteriaA
      query:
        description: A query.
        type: object

Шаги для воспроизведения

Код клиента Java, сгенерированный swagger codegen, выглядит следующим образом:

Интерфейс:

public interface OneOfTestRequestCriteria {}

Конкретный класс:

@Schema(description = "")
@javax.annotation.Generated(value = "io.swagger.codegen.v3.generators.java.JavaClientCodegen", date = "2020-01-28T13:06:29.942Z[Europe/London]")
public class CriteriaA implements OneOfTestRequestCriteria {

  @JsonAdapter(TypeEnum.Adapter.class)
  public enum TypeEnum {
    CriteriaA("CriteriaA");

    private String value;

    TypeEnum(String value) {
      this.value = value;
    }
    public String getValue() {
      return value;
    }

    @Override
    public String toString() {
      return String.valueOf(value);
    }
    public static TypeEnum fromValue(String text) {
      for (TypeEnum b : TypeEnum.values()) {
        if (String.valueOf(b.value).equals(text)) {
          return b;
        }
      }
      return null;
    }
    public static class Adapter extends TypeAdapter<TypeEnum> {
      @Override
      public void write(final JsonWriter jsonWriter, final TypeEnum enumeration) throws IOException {
        jsonWriter.value(enumeration.getValue());
      }

      @Override
      public TypeEnum read(final JsonReader jsonReader) throws IOException {
        String value = jsonReader.nextString();
        return TypeEnum.fromValue(String.valueOf(value));
      }
    }
  }  @SerializedName("type")
  private TypeEnum type = null;

  @SerializedName("query")
  private Object query = null;

  public CriteriaA type(TypeEnum type) {
    this.type = type;
    return this;
  }

  @Schema(required = true, description = "")
  public TypeEnum getType() {
    return type;
  }

  public void setType(TypeEnum type) {
    this.type = type;
  }

  public CriteriaA query(Object query) {
    this.query = query;
    return this;
  }

  @Schema(required = true, description = "")
  public Object getQuery() {
    return query;
  }

  public void setQuery(Object query) {
    this.query = query;
  }


  @Override
  public boolean equals(java.lang.Object o) {
    if (this == o) {
      return true;
    }
    if (o == null || getClass() != o.getClass()) {
      return false;
    }
    CriteriaA criteriaA = (CriteriaA ) o;
    return Objects.equals(this.type, criteriaA.type) &&
        Objects.equals(this.query, criteriaA.query);
  }

  @Override
  public int hashCode() {
    return Objects.hash(type, query);
  }


  @Override
  public String toString() {
    StringBuilder sb = new StringBuilder();
    sb.append("class CriteriaA {\n");

    sb.append("    type: ").append(toIndentedString(type)).append("\n");
    sb.append("    query: ").append(toIndentedString(query)).append("\n");
    sb.append("}");
    return sb.toString();
  }

  private String toIndentedString(java.lang.Object o) {
    if (o == null) {
      return "null";
    }
    return o.toString().replace("\n", "\n    ");
  }

}

I ' m пытается использовать этот сгенерированный клиентский код для отправки запроса:

final TestRequest testRequest = new TestRequest();

final CriteriaA criteriaA = new CriteriaA ();
criteriaA .setType(CriteriaA .TypeEnum.CriteriaA);
criteriaA .setQuery("a query");

testRequest .setCriteria(criteriaA );

final ApiResponse<Void> apiResponse = testApi.createOrUpdateTestWithHttpInfo(testRequest);

Запуск вышеуказанного клиентского кода приводит к этой ошибке, когда Джексон пытается десериализовать его. Кажется, что он пытается создать экземпляр интерфейса OneOfTestRequestCriteria вместо конкретной реализации интерфейса; Критерии A:

[Ошибка обработки запроса; вложенным исключением является org.springframework.http.converter.HttpMessageConversionException: ошибка определения типа: [простой тип, класс com.acme.tag.models.OneOfTestRequestCriteria]; вложенное исключение: com.faster xml .jackson.databind.ex c .InvalidDefinitionException: невозможно создать экземпляр com.acme.tag.models.OneOfTestRequestCriteria (не существует создателей, таких как конструкция по умолчанию): абстрактные типы также не нужны быть сопоставленным с конкретными типами, иметь пользовательский десериализатор или содержать дополнительную информацию о типе \ n

Если я аннотирую сгенерированный интерфейс:

public interface OneOfTestRequestCriteria {}

со следующим:

@JsonTypeInfo(
  use = JsonTypeInfo.Id.NAME, 
  include = JsonTypeInfo.As.PROPERTY, 
  property = "type")
@JsonSubTypes({ 
  @Type(value = CriteriaA.class, name = "CriteriaA")
})
public interface OneOfTestRequestCriteria {

}

Затем запрос корректно десериализуется в CriteriaA - я что-то упустил в своем swagger.yaml, что привело бы к тому, что этот интерфейс не был аннотирован инструментом codegen?

1 Ответ

1 голос
/ 27 марта 2020
<groupId>io.swagger.codegen.v3</groupId>
<artifactId>swagger-codegen-maven-plugin</artifactId>
<version>3.0.18</version>

См. Также: https://github.com/swagger-api/swagger-codegen-generators/pull/585

...