ОТДЫХ. Джерси. Как программно выбрать тип возвращаемого значения: JSON или XML?

У меня есть 2 вопроса:

1. Могу ли я создать класс один, аннотировать его аннотациями JAXB (для поддержки XML) и объявить в web.xml

<init-param>
    <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
    <param-value>true</param-value>
</init-param>

для поддержки библиотеки JSON (Jackson)? Или мне нужно создать отдельно два класса для JSON и XML?

Или может существовать еще более элегантный способ заставить службу REST возвращать JSON и XML?

2. Как я могу программным образом выбрать тип возвращаемого типа (JSON или XML)?

Спасибо.

Ответ 1

Если ваш клиент хочет использовать часть URL для настройки типа ответа, вы можете использовать фильтр Servlet.

Легкий способ реализации переопределения представления (тип носителя) может использовать параметр запроса URL:

/ресурсы/TODO? = Формат JSON

Фильтр Servlet анализирует параметры URL-запроса, и если присутствует формат = json, заменяет или добавляет заголовок принятия "application/json".

Ответ 2

Примечание. Я EclipseLink JAXB (MOXy) и член экспертная группа JAXB (JSR-222).


Можно ли создать один класс, аннотировать его с помощью аннотаций JAXB (для поддержки XML) и объявить в web.xml для поддержки библиотеки JSON (Jackson)?

Вы всегда можете использовать класс Application для указания MessageBodyReader/MessageBodyWriter для привязки JSON. Я считаю, что Джексон выполняет реализацию в своей банке. Ниже приведен пример класса Application, который указывает MOXy как поставщика JSON:

package org.example;

import java.util.*;
import javax.ws.rs.core.Application;
import org.eclipse.persistence.jaxb.rs.MOXyJsonProvider;

public class CustomerApplication  extends Application {

    @Override
    public Set<Class<?>> getClasses() {
        HashSet<Class<?>> set = new HashSet<Class<?>>(2);
        set.add(MOXyJsonProvider.class);
        set.add(CustomerService.class);
        return set;
    }

}

Или мне нужно создать отдельно два класса для JSON и XML?

EclipseLink JAXB (MOXy) предлагает встроенную привязку XML и предназначен для использования той же объектной модели для JSON и XML. Вы можете интегрировать его в свое приложение JAX-RS, используя класс MOXyJsonProvider:


Как я могу программным образом выбрать, какой тип будет возвращен (JSON или XML)?

Сторона сервера

Вы можете указать, что ваша служба предлагает как сообщения XML, так и JSON с помощью аннотации @Produces.

@GET
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
@Path("{id}")
public Customer read(@PathParam("id") long id) {
    return entityManager.find(Customer.class, id);
}

Дополнительная информация

Клиентская сторона

Вы можете использовать MediaType для указания типа сообщения. Ниже приведен пример использования клиентских API-интерфейсов. Обратите внимание, что URL-адрес один и тот же, только тип запрашиваемого носителя отличается.

Client client = Client.create();
WebResource resource = client.resource("http://localhost:8080/CustomerService/rest/customers");

// Get XML response as a Customer
Customer customer = resource.path("1")
    .accept(MediaType.APPLICATION_XML)
        .get(Customer.class);
System.out.println(customer.getLastName() + ", "+ customer.getFirstName());

// Get JSON response as a Customer
Customer customer = resource.path("1")
    .accept(MediaType.APPLICATION_JSON)
        .get(Customer.class);
System.out.println(customer.getLastName() + ", "+ customer.getFirstName());

Дополнительная информация

Ответ 3

Нет необходимости в отдельных классах, вам нужны отдельные методы:

@GET
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public Todo getXML() {
    Todo todo = new Todo();
    todo.setSummary("This is my first todo");
    todo.setDescription("This is my first todo");
    return todo;
}

Затем на стороне клиента, когда вы запрашиваете услугу, вы указываете, в каком формате вы хотите:

// Get XML
System.out.println(service.path("rest").path("todo").accept(MediaType.TEXT_XML).get(String.class));
// Get XML for application
System.out.println(service.path("rest").path("todo").accept(MediaType.APPLICATION_XML).get(String.class));
// Get JSON for application
System.out.println(service.path("rest").path("todo").accept(MediaType.APPLICATION_JSON).get(String.class));