swagger2 polymorphisme:向swagger文档添加抽象类列表

时间:2017-04-12 09:04:56

标签: java spring-boot swagger-ui swagger-2.0

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

假设我有一个抽象类Person和两个子类Child和Adult。在我的请求中,我有一个Person列表,其中可以包含Child对象和Adult对象。

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

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

有谁知道如何做到这一点?

谢谢!

1 个答案:

答案 0 :(得分: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() {
   }
}