提问者:小点点

swagger2多态:将抽象类列表添加到swagger留档


我有一个带有swagger2的spring-boot应用程序。我希望能够将父对象列表映射到swagger中的请求模型。我正在使用注解atm,但也可以使用yaml文件。

假设我有一个抽象类Person和两个子类儿童和成人。在我的请求中,我有一个可以包含儿童对象和成人对象的Person列表。

@JsonTypeInfo(
      use = JsonTypeInfo.Id.NAME,
      include = JsonTypeInfo.As.PROPERTY,
      property = "type",
      visible = true)
@JsonSubTypes({
      @JsonSubTypes.Type(value = Child.class, name = "CHILD"),
      @JsonSubTypes.Type(value = Adult.class, name = "ADULT")})
@ApiModel(value = "Child", subTypes = {Child.class, Adult.class}, discriminator = "type")
public abstract class Person { 
   @ApiModelProperty(notes = "Name of the person", example = "aaron")
   private String name;
   @ApiModelProperty(notes = "Birthdate of the person", example = "2000-07-10")
   private Date birthDate;
   @ApiModelProperty(notes = "Type of the person ('CHILD' or 'ADULT')", example = "CHILD")
   private String type;

   Child(String name, LocalDate birthdate) {
    this.name = name;
    this.birthdate = birthdate;
   }

   Child() {
   }
}

public class Adult extends Person { 
   private String job;

   public Adult(String name, Date birthdate, String job) {
      super(name, birthdate);
      this.job = job;
   }

   Adult() {
   }
}

public class Child extends Person { 
   private List<String> toys;

   public Child(String name, Date birthdate, List<String> toys) {
      super(name, birthdate);
      this.toys = toys;
   }

   Child() {
   }
}

我的请求对象如下所示:

public class PersonRequest {

@ApiModelProperty(notes = "Year of insert", example = "2019")
private Integer year;

@ApiModelProperty(notes = "Month of insert", example = "1")
private Integer month;

@ApiModelProperty(notes = "List of persons")
private List<Person> persons;

public SimulationRequest(Integer year, Integer month, List<Person> persons) {
    this.year = year;
    this.month = month;
    this.persons = persons;
}

private SimulationRequest() {
}

public Integer getYear() {
    return year;
}

public Integer getMonth() {
    return month;
}

public List<Person> getPersons() {
    return persons;
}
}

我无法获得大摇大摆的用户界面来显示正确的模型,我现在得到的是:

PersonRequest {
  persons (Array[Person], optional): List of persons ,
  month (integer, optional): Month of insert ,
  year (integer, optional): Year of insert
}Person {
 name (string, optional): Birthdate of the person ,
 birthDate (string, optional): Name of the person ,
 type (string, optional): Type of the person ('CHILD' or 'ADULT')
}

我想要的是这样的东西:

PersonRequest {
  persons (Array[Person], optional): List of persons ,
  month (integer, optional): Month of insert ,
  year (integer, optional): Year of insert
}Child {
 name (string, optional): Birthdate of the person ,
 birthDate (string, optional): Name of the person ,
 type (string, optional): Type of the person ('CHILD' or 'ADULT')
 toys (Array[string], optional): Toys of the child
}Adult {
 name (string, optional): Birthdate of the person ,
 birthDate (string, optional): Name of the person ,
 type (string, optional): Type of the person ('CHILD' or 'ADULT')
 job (string, optional): Job of the adult
}

并带有示例值

{
 "persons": [
  {
     "birthdate": "2000-07-10",
     "name": "aaron",
     "type": "CHILD",
     "toys" : ["ball","lego"]
  },
  {
     "birthdate": "1990-07-10",
     "name": "sofia",
     "type": "ADULT",
     "job" : "developer"
  }
],
"month": 6,
"year": 2019
}

我在留档中搜索过,但似乎没有找到我的问题的正确答案。我已经查看了这个线程,并在swagger编辑器中遵循了petstore示例。但我似乎没有找到如何在Swagger中使用抽象类的列表/数组。

有人知道怎么做吗?

谢谢!


共1个答案

匿名用户

这是我的示例,使用Lombok和Swagger 3注释。诀窍是在带有抽象类型的排序规则上使用“oneOf”或“anyOf”。有关详细信息,请参阅https://swagger.io/docs/specification/describing-request-body/。

@Data
public class PersonRequest {

@Schema(description = "Either Child or Adult",
           anyOf = {Child .class, Adult.class})
private List<? extends Person> persons;

}

public enum PersonType {
        PARENT, CHILD
    }

@Data
public abstract class Person { 
   
   @Schema(notes = "Name of the person", example = "aaron")
   private String name;
   
   @Schema(notes = "Birthdate of the person", example = "2000-07-10")
   @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
   private Date birthDate;
   
   @Schema(notes = "Type of the person ('CHILD' or 'ADULT')", example = "CHILD")
   private PersonType type; //this should be one of the enum values

   Child(String name, LocalDate birthdate) {
    this.name = name;
    this.birthdate = birthdate;
   }

   Child() {
   }
}

@Data
@EqualsAndHashCode(callSuper = true)
public class Adult extends Person { 
   private String job;

   public Adult(String name, Date birthdate, String job) {
      super(name, birthdate);
      this.job = job;
   }

   Adult() {
   }
}

@Data
@EqualsAndHashCode(callSuper = true)
public class Child extends Person { 
   private List<String> toys;

   public Child(String name, Date birthdate, List<String> toys) {
      super(name, birthdate);
      this.toys = toys;
   }

   Child() {
   }
}