Search code examples
javaspring-bootjackson2jackson-dataformat-xml

Customize Jackson XML output when using @JsonView in Spring Boot


I am using the @JsonView annotation to output a simplified version of a complex object in Spring MVC.

The View:

public class UserView {
    public interface Summary {}
}

The entity class:

public class User implements Serializable {

    private static final long serialVersionUID = 1L;

    @Column(name = "name", length = 255)
    @JsonView(UserView.Summary.class)
    private String name;

The resource method:

@GetMapping(value = "users", produces = {MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_UTF8_VALUE})
@JsonView(UserView.Summary.class)
public List<User> getAllUsers() {
    return userRepository.findAllBy();
}

This works perfect when outputting JSON:

[
    {"name": "User 1"},
    {"name": "User 2"}
]

But when the "Content-Type" is set to XML, the following output is returned:

<List>
    <item>
        <name>User 1</name>
    </item>
    <item>
        <name>User 2</name>
    </item>
</List>

I'd like to have <Users> instead of <List> and <User> instead of <item>, but I couldn't find a way of changing these generic names. I've tried annotations like @XmlRootElement(name="user") or @XmlElementWrapper(name="users"), but no luck.


Solution

  • Using @XmlElementWrapper is generally a good way to do that. But this only works when the list is inside an entity.

    I'd recommend to not return List<User> but instead a Users Entity (notice the plural) with the attribute users. We can even omit the @XmlElementWrapper here since the Entity itself is the element wrapper.

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

    Output

    <Users>
        <User>
            <name>User 1</name>
        </User>
        <User>
            <name>User 2</name>
        </User>
    </Users>