Как я могу настроить сериализацию списка объектов JAXB к JSON?

StackOverflow https://stackoverflow.com/questions/2199453

Вопрос

Я использую Джерси, чтобы создать веб-сервис отдыха для компонента сервера.

Jaxb-аннотированный объект, который я хочу сериализовать в списке, выглядит так:

@XmlRootElement(name = "distribution")
@XmlType(name = "tDistribution", propOrder = {
    "id", "name"
})
public class XMLDistribution {
    private String id;
    private String name;
    // no-args constructor, getters, setters, etc
}

У меня есть ресурс отдыха, чтобы получить одно распределение, которое выглядит так:

@Path("/distribution/{id: [1-9][0-9]*}")
public class RESTDistribution {
    @GET
    @Produces("application/json")
    public XMLDistribution retrieve(@PathParam("id") String id) {
        return retrieveDistribution(Long.parseLong(id));
    }
    // business logic (retrieveDistribution(long))
}

У меня также есть ресурс отдыха для получения списка всех распределений, который выглядит так:

@Path("/distributions")
public class RESTDistributions {
    @GET
    @Produces("application/json")
    public List<XMLDistribution> retrieveAll() {
        return retrieveDistributions();
    }
    // business logic (retrieveDistributions())
}

Я использую ContexTresolver, чтобы настроить сериализацию JAXB, который в настоящее время настроен так:

@Provider
@Produces("application/json")
public class JAXBJSONContextResolver implements ContextResolver<JAXBContext> {
    private JAXBContext context;
    public JAXBJSONContextResolver() throws Exception {
        JSONConfiguration.MappedBuilder b = JSONConfiguration.mapped();
        b.nonStrings("id");
        b.rootUnwrapping(true);
        b.arrays("distribution");
        context = new JSONJAXBContext(b.build(), XMLDistribution.class);
    }
    @Override
    public JAXBContext getContext(Class<?> objectType) {
        return context;
    }
}

Оба ресурсов отдыха работают, а также контекстный Resolver. Это пример вывода для первого:

// path: /distribution/1
{"id":1,"name":"Example Distribution"}

Что именно то, что я хочу. Это пример вывода для списка:

// path: /distributions
{"distribution":[{"id":1,"name":"Sample Distribution 1"},{"id":2,"name":"Sample Distribution 2"}]}

Что не совсем то, что я хочу.

Я не понимаю, почему есть ограждение distribution Теги там. Я хотел удалить это с .rootUnwrapping(true) В контексте Resolver, но, по-видимому, это удаляет только еще один ограждающий тег. Это вывод с .rootUnwrapping(false):

// path: /distribution/1
{"distribution":{"id":1,"name":"Example Distribution"}} // not ok
// path: /distributions
{"xMLDistributions":{"distribution":[{"id":1,"name":"Sample Distribution 1"},{"id":2,"name":"Sample Distribution 2"}]}}

Я также должен был настроить .arrays("distribution") Чтобы всегда получить массив JSON даже с одним элементом.

В идеале я хотел бы иметь это как выход:

// path: /distribution/1
{"id":1,"name":"Example Distribution"} // currently works
// path: /distributions
[{"id":1,"name":"Sample Distribution 1"},{"id":2,"name":"Sample Distribution 2"}]

Я пытался вернуть List<XMLDistribution>, А. XMLDistributionList (обертка вокруг списка), XMLDistribution[], Но я не смог найти способ получить простой JSON Array распределений в моем обязательном формате.

Я также попробовал другие обозначения, возвращаемые JSONConfiguration.natural(), JSONConfiguration.mappedJettison(), и т. Д., И не мог получить что-нибудь, напоминающее то, что мне нужно.

Кто-нибудь знает, можно ли настроить JAXB для этого?

Это было полезно?

Решение

Я нашел решение: замените jaxb json serializer с лучшим ведущим сериатором JSON, как Джексон. Легкий способ - использовать Jackson-Jaxrs, который уже сделал это для вас. Класс - ДжексонжсонПровидер. Все, что вам нужно сделать, это редактировать Web.xml вашего проекта, так что Джерси (или другое JAX-RS реализация) сканирует для него. Вот что нужно добавить:

<init-param>
  <param-name>com.sun.jersey.config.property.packages</param-name>
  <param-value>your.project.packages;org.codehaus.jackson.jaxrs</param-value>
</init-param>

И это все, что есть к этому. Джексон будет использоваться для сериализации JSON, и он работает так, как вы ожидаете за списки и массивы.

Чем дольше - написать свой собственный пользовательский Message CodyWriter, зарегистрированный для производства «приложения / JSON». Вот пример:

@Provider @Produces («Применение / JSON») Открытый класс JSONMessagebodyWomeWriter ImsonmessageBodywriter Illyments CodyWrader {@ @ override Public Tongetate (объект OBJ, тип класса, тип генеристы, аннотация [] аннотации, Mediatype Mediatype) {return -1; } @ Override Public Boolean Iswritable (тип класса, тип генерицину, аннотации аннотации [], Mediatype Mediatype) {возвращается истина; } @ Override Public Void Writeto (Цель объекта, Тип класса, тип генерицирован, аннотация [] Annotations, Mediatype Mediatype, MultivaluedMap Httpheaders, Outputsee yumps) бросает IOException {Новый объектMapper (). }}

Вам нужно будет убедиться, что ваш Web.xml включает в себя пакет, как для готового решения выше.

В любом случае: Вуаля! Вы увидите правильно сформированные JSON.

Вы можете скачать Джексон отсюда:http://jackson.codehaus.org/

Другие советы

Ответ Джонатана отлично, и это было очень полезно для меня.

Просто обновление:

Если вы используете версию 2.x of Jackson (например, версия 2.1) класс COM.Fasterxml.jackson.jaxrs.json.jacksonjaxbjsonprovider, поэтому web.xml:

<init-param>
  <param-name>com.sun.jersey.config.property.packages</param-name>
  <param-value>your.project.packages;com.fasterxml.jackson.jaxrs.json</param-value>
</init-param>
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top