Настройте вывод XML Джексона при использовании @JsonView в Spring Boot

Я использую аннотацию @JsonView для вывода упрощенной версии сложного объекта в Spring MVC.

Вид:

public class UserView {
    public interface Summary {}
}

Класс сущности:

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"), но безуспешно.


person kioleanu    schedule 22.03.2020    source источник
comment
Не могли бы вы прокомментировать ответы? Спасибо.   -  person s7vr    schedule 29.03.2020
comment
Привет @SagarVeeram, да, извини. Я пробовал оба ответа, и они оба работают. Я собираюсь принять первое, что было предоставлено. Большое спасибо за оба ваших вклада!   -  person kioleanu    schedule 29.03.2020
comment
@viorel В моем случае JsonView не влияет на вывод xml, но json отображается отлично. Как вы заставили свою работу, не могли бы вы поделиться.   -  person bitsobits    schedule 11.11.2020


Ответы (2)


Использование @XmlElementWrapper обычно является хорошим способом сделать это. Но это работает только тогда, когда список находится внутри объекта.

Я бы рекомендовал не возвращать List<User>, а вместо этого Users Entity (обратите внимание на множественное число) с атрибутом users. Мы можем даже опустить здесь @XmlElementWrapper, так как сама Entity является оболочкой элемента.

@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>
person jdickel    schedule 26.03.2020

Поддержка коллекций на корневом уровне ограничена для xml mapper (см. json-generated-by-jackson">здесь и здесь (ответы немного устарели, но вы должны понять), но коллекции как свойство 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>
person s7vr    schedule 26.03.2020