Spring Boot返回列表的REST接口springdoc XML Schema异常及标签修改问题
问题背景
我在Spring Boot应用中编写了如下@RestController:
package test.controllers; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.Arrays; import java.util.List; @RestController @RequestMapping("/test") public class TestController { public static class Person { public String fullName; public Person(String fullName) { this.fullName = fullName; } } @GetMapping(value = "", produces = {"application/json", "application/xml"}) public List<Person> getPeople() { return Arrays.asList(new Person("Name1"), new Person("Name2")); } }
接口返回的XML格式:
<List> <item> <FullName>Name1</FullName> </item> <item> <FullName>Name2</FullName> </item> </List>
返回的JSON格式:
[{"FullName":"Name1"},{"FullName":"Name2"}]
springdoc生成的OpenAPI代码存在问题:
{ "/test" : { "get" : { "tags" : [ "test-controller" ], "operationId" : "getPeople", "responses" : { "200" : { "description" : "OK", "content" : { "application/json" : { "schema" : { "type" : "array", "items" : { "$ref" : "#/components/schemas/Person" } } }, "application/xml" : { "schema" : { "type" : "array", "items" : { "$ref" : "#/components/schemas/Person" } } } } } } } }, "components" : { "schemas" : { "Person" : { "type" : "object", "properties" : { "fullName" : { "type" : "string" } }, "description" : "" } } } }
具体问题
- JSON格式无问题,但XML格式的文档中未提及List/item标签,且Swagger UI中XML示例报错“XML example cannot be generated; root element name is undefined”。必须返回列表且需要OpenAPI文档的情况下,正确的处理方式是什么?
- 如何修改XML中的List和item标签名称?
我尝试过继承ArrayList、将List<Person>作为类的属性、使用多种注解,但均未在保留期望返回结构的前提下达到预期效果。
解决方案
问题1:修复OpenAPI文档的XML结构与示例生成
核心是给返回的列表定义明确的包装类,通过JAXB注解指定XML结构,同时让springdoc能识别完整的XML层级。
修改后的代码如下:
package test.controllers; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import jakarta.xml.bind.annotation.XmlElement; import jakarta.xml.bind.annotation.XmlRootElement; import com.fasterxml.jackson.annotation.JsonUnwrapped; import java.util.Arrays; import java.util.List; @RestController @RequestMapping("/test") public class TestController { @XmlRootElement(name = "PersonList") // 指定XML根节点名称 public static class PersonListWrapper { private List<Person> persons; public PersonListWrapper() {} // JAXB要求必须有无参构造 public PersonListWrapper(List<Person> persons) { this.persons = persons; } @JsonUnwrapped // 让JSON返回保持原数组格式,不被包装 @XmlElement(name = "Person") // 指定列表元素的XML标签名 public List<Person> getPersons() { return persons; } public void setPersons(List<Person> persons) { this.persons = persons; } } public static class Person { @XmlElement(name = "FullName") // 保持XML字段标签为FullName public String fullName; public Person() {} // JAXB要求必须有无参构造 public Person(String fullName) { this.fullName = fullName; } } @GetMapping(value = "", produces = {"application/json", "application/xml"}) public PersonListWrapper getPeople() { return new PersonListWrapper(Arrays.asList(new Person("Name1"), new Person("Name2"))); } }
修改后效果:
- XML返回带有明确的根节点和子节点结构,springdoc会自动识别该结构,Swagger UI可正常生成XML示例
- JSON返回保持原数组格式
[{"FullName":"Name1"},{"FullName":"Name2"}],无需额外调整
问题2:修改XML中的List和item标签名称
直接通过JAXB注解自定义标签名:
@XmlRootElement(name = "自定义根标签名"):替换原<List>根标签@XmlElement(name = "自定义子标签名"):替换原<item>子元素标签
比如将根标签设为EmployeeList,子标签设为Employee,只需修改对应注解的name参数:
@XmlRootElement(name = "EmployeeList") public static class PersonListWrapper { // ... @XmlElement(name = "Employee") public List<Person> getPersons() { return persons; } }
最终XML返回会变为:
<EmployeeList> <Employee> <FullName>Name1</FullName> </Employee> <Employee> <FullName>Name2</FullName> </Employee> </EmployeeList>
内容的提问来源于stack exchange,提问作者Andrew Barhatov
相关产品推荐
相关产品推荐

