Я использую Джерси для создания веб-сервиса REST для серверного компонента.
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
}
У меня есть ресурс REST для получения одного распределения, которое похоже на это:
@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))
}
У меня также есть ресурс REST для получения списка всех дистрибутивов, который похож на это:
@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;
}
}
Обе работы ресурсов REST, а также преобразователь контекста. Это - пример вывода для первого:
// 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)
в преобразователе контекста, но по-видимому который только удаляет другой тег включения. Это - вывод с .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"}]
Я пытался возвратить a List<XMLDistribution>
, a XMLDistributionList
(обертка вокруг списка), a XMLDistribution[]
, но я не мог найти способ получить простой массив JSON дистрибутивов в моем требуемом формате.
Я также попробовал другие нотации, возвращенные JSONConfiguration.natural()
, JSONConfiguration.mappedJettison()
, и т.д., и ничего не мог получить сходство, в чем я нуждаюсь.
Кто-либо знает, возможно ли настроить JAXB, чтобы сделать это?
Я нашел решение: заменить сериализатор JAXB JSON на сериализатор JSON с лучшими характеристиками, например, Jackson. Самый простой способ - использовать jackson-jaxrs, который уже сделал это за вас. Класс - JacksonJsonProvider. Все, что вам нужно сделать, это отредактировать файл web.xml вашего проекта так, чтобы Jersey (или другая реализация 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, и он работает так, как вы ожидаете, для списков и массивов.
Более длительный способ - написать свой собственный MessageBodyWriter, зарегистрированный для создания «application / json». Вот пример:
@Provider @Produces("application/json") public class JsonMessageBodyWriter implements MessageBodyWriter { @Override public long getSize(Object obj, Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { return -1; } @Override public boolean isWriteable(Class type, Type genericType, Annotation annotations[], MediaType mediaType) { return true; } @Override public void writeTo(Object target, Class type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap httpHeaders, OutputStream outputStream) throws IOException { new ObjectMapper().writeValue(outputStream, target); } }
Вам нужно убедиться, что ваш web.xml включает пакет, как и для готового решения выше.
В любом случае: вуаля! Вы увидите правильно сформированный JSON.
Вы можете скачать Джексона отсюда: http://jackson.codehaus.org/