在 Spring Boot 中使用 @JsonView 时自定义 Jackson XML 输出
Customize Jackson XML output when using @JsonView in Spring Boot
我正在使用 @JsonView
注释在 Spring MVC 中输出复杂对象的简化版本。
观点:
public class UserView {
public interface Summary {}
}
实体class:
public class User implements Serializable {
private static final long serialVersionUID = 1L;
@Column(name = "name", length = 255)
@JsonView(UserView.Summary.class)
private String name;
资源方法:
@GetMapping(value = "users", produces = {MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_UTF8_VALUE})
@JsonView(UserView.Summary.class)
public List<User> getAllUsers() {
return userRepository.findAllBy();
}
这在输出 JSON 时非常有效:
[
{"name": "User 1"},
{"name": "User 2"}
]
但是当"Content-Type"设置为XML时,返回如下输出:
<List>
<item>
<name>User 1</name>
</item>
<item>
<name>User 2</name>
</item>
</List>
我想要 <Users>
而不是 <List>
和 <User>
而不是 <item>
,但我找不到更改这些通用名称的方法.我试过像 @XmlRootElement(name="user")
或 @XmlElementWrapper(name="users")
这样的注释,但没有成功。
使用 @XmlElementWrapper
通常是一个很好的方法。
但这仅在列表位于实体内部时有效。
我建议不要 return List<User>
,而是 Users
具有属性 users
的实体(注意复数形式)。
我们甚至可以在这里省略 @XmlElementWrapper
,因为实体本身就是元素包装器。
@XmlRootElement
public class Users implements Serializable {
private static final long serialVersionUID = 1337L;
@XmlElement(name = "User")
private List<User> users = new ArrayList<>();
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
}
输出
<Users>
<User>
<name>User 1</name>
</User>
<User>
<name>User 2</name>
</User>
</Users>
根级别的集合对 xml 映射器的支持有限(请参阅 here and here(答案有点过时,但您应该明白了),但是作为 pojo 属性 的集合是完整的支持。所以对于自定义,最好创建一个包装器。
还要注意包装器 属性 的 @JsonView(UserView.Summary.class) 以便 spring 将其拾取。
类似
@JacksonXmlRootElement(localName = "Users")
public class CollectionWrapper {
@JacksonXmlElementWrapper(useWrapping = false)
@JacksonXmlProperty(localName = "User")
@JsonView(UserView.Summary.class)
private List<User> users;
public CollectionWrapper(List<User> users) {
this.users = users;
}
}
资源
@GetMapping(value = "users", produces = {MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_UTF8_VALUE})
@JsonView(UserView.Summary.class)
public CollectionWrapper getAllUsers() {
return new CollectionWrapper(userRepository.findAllBy());
}
输出
<Users>
<User>
<name>User 1</name>
</User>
<User>
<name>User 2</name>
</User>
</Users>
我正在使用 @JsonView
注释在 Spring MVC 中输出复杂对象的简化版本。
观点:
public class UserView {
public interface Summary {}
}
实体class:
public class User implements Serializable {
private static final long serialVersionUID = 1L;
@Column(name = "name", length = 255)
@JsonView(UserView.Summary.class)
private String name;
资源方法:
@GetMapping(value = "users", produces = {MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_UTF8_VALUE})
@JsonView(UserView.Summary.class)
public List<User> getAllUsers() {
return userRepository.findAllBy();
}
这在输出 JSON 时非常有效:
[
{"name": "User 1"},
{"name": "User 2"}
]
但是当"Content-Type"设置为XML时,返回如下输出:
<List>
<item>
<name>User 1</name>
</item>
<item>
<name>User 2</name>
</item>
</List>
我想要 <Users>
而不是 <List>
和 <User>
而不是 <item>
,但我找不到更改这些通用名称的方法.我试过像 @XmlRootElement(name="user")
或 @XmlElementWrapper(name="users")
这样的注释,但没有成功。
使用 @XmlElementWrapper
通常是一个很好的方法。
但这仅在列表位于实体内部时有效。
我建议不要 return List<User>
,而是 Users
具有属性 users
的实体(注意复数形式)。
我们甚至可以在这里省略 @XmlElementWrapper
,因为实体本身就是元素包装器。
@XmlRootElement
public class Users implements Serializable {
private static final long serialVersionUID = 1337L;
@XmlElement(name = "User")
private List<User> users = new ArrayList<>();
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
}
输出
<Users>
<User>
<name>User 1</name>
</User>
<User>
<name>User 2</name>
</User>
</Users>
根级别的集合对 xml 映射器的支持有限(请参阅 here and here(答案有点过时,但您应该明白了),但是作为 pojo 属性 的集合是完整的支持。所以对于自定义,最好创建一个包装器。
还要注意包装器 属性 的 @JsonView(UserView.Summary.class) 以便 spring 将其拾取。
类似
@JacksonXmlRootElement(localName = "Users")
public class CollectionWrapper {
@JacksonXmlElementWrapper(useWrapping = false)
@JacksonXmlProperty(localName = "User")
@JsonView(UserView.Summary.class)
private List<User> users;
public CollectionWrapper(List<User> users) {
this.users = users;
}
}
资源
@GetMapping(value = "users", produces = {MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_UTF8_VALUE})
@JsonView(UserView.Summary.class)
public CollectionWrapper getAllUsers() {
return new CollectionWrapper(userRepository.findAllBy());
}
输出
<Users>
<User>
<name>User 1</name>
</User>
<User>
<name>User 2</name>
</User>
</Users>