Джерси: верните список строк
Я пытаюсь вернуть список строк в Джерси как JSON и XML.
Я думал, что это будет тривиально.
Моя первая попытка была написать что-то вроде этого
@GET
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Path("/bar")
public List<String> get() {
return dao.get();
}
и я ожидал вывода, аналогичного этому: [ "string1",..., "stringN]
к сожалению, я получил это:
com.sun.jersey.api.MessageException: A message body writer for Java class java.util.LinkedList, and Java type java.util.List<java.lang.String>, and MIME media type application/json was not found
Затем я написал оболочку StringList для List
@XmlRootElement
public class StringList {
private List<String> data;
public StringList() {
}
public StringList(List<String> data) {
this.data = data;
}
public List<String> getData() {
return data;
}
public void setData(List<String> data) {
this.data = data;
}
}
и изменил фасад на
@GET
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Path("/foo")
public StringList stringlist() {
return new StringList(sl());
}
Что отлично подходит для списков с большим количеством элементов, чем 1.
{"data":["foo","bar"]}
К сожалению, я получаю два невыраженных результата для одного или нулевого элемента
{"data": "just one"} // for one element i would expect {"data": ["just one"]}
null // for no elements i would expect {"data": []}
Я делаю что-то совершенно неправильно?
Как я могу это исправить?
Ответы
Ответ 1
вы можете использовать javax.ws.rs.core.GenericEntity:
@GET
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Path("/foo")
public GenericEntity<List<String>> stringlist()
{
List<String> list = Arrays.asList("test", "as");
return new GenericEntity<List<String>>(list) {};
}
Ответ 2
Хорошо, я мог бы исправить это, выполнив поиск образцов
Это работает, но его можно использовать только для JSON, а не для XML
@GET
@Produces({MediaType.APPLICATION_JSON})
@Path("/get")
public JSONArray get() {;
return new JSONArray(dao.getStringList());
}
Исправлена проблема, но есть ли общий подход?
Ответ 3
Чтобы убедить Джерси выводить списки так, как вы хотите, вам нужно предоставить собственный ContextResolver:
@Provider
public class JaxbContentResolver implements ContextResolver<JAXBContext> {
private Log log = LogFactory.getLog(getClass());
private JAXBContext context;
public JaxbContentResolver() throws JAXBException {
Class[] types = {StringList.class};
context = new JSONJAXBContext(JSONConfiguration.mapped().rootUnwrapping(true).arrays("data").build(), types);
}
@Override
public JAXBContext getContext(Class<?> objectType) {
log.trace("Entering Test-getContext for type: " + objectType.getSimpleName());
return context;
}
}
Таким образом, списки появятся так, как вы хотите.
ПРИМЕЧАНИЕ. Одна из недостатков этого подхода заключается в том, что вам нужно поддерживать еще одно место в коде; в случае, если вы хотите добавить в свой REST-интерфейс другой класс (список оберток), вам нужно помнить, что нужно перейти к предыдущему коду и добавить этот класс в свой ContextResolver...
Ответ 4
Вам нужно использовать альтернативную конфигурацию JSON JSONConfiguration.natural()
.
Лучше всего создать свой собственный ContextResolver
, используя эту альтернативную конфигурацию в качестве поставщика, и сообщить, на какие классы он отвечает.
Я не знаю, как использовать альтернативную конфигурацию по-другому.
Ответ 5
В дополнение к предоставленным ответам, если вы все еще получаете MessageBodyWriter not found
, попробуйте добавить зависимость, например:
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
</dependency>
Ответ 6
Мое решение для этого было классом-оболочкой (нашло его где-то). Он работает сейчас. Я не понимаю мысли, не поддерживающие класс javas List как корневой элемент. Возможно, это связано с некоторыми спецификациями json/лучшей практикой, о которых я не знаю.
Но теперь im использует это:
public class Houses {
private List<String> houses;
// Needed for jersey
public Houses() { }
public Houses(List<String> houses) {
this.houses = houses;
}
public void setHouses(List<String> houses) {
this.houses = houses;
}
public List<String> getHouses() {
return this.houses;
}
}