Джерси: вернуть список строк - PullRequest
17 голосов
/ 22 марта 2011

Я пытаюсь вернуть список строк в Джерси в формате 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 для списка

@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": []}

Я что-то делаю не так? Как я могу это исправить?

Ответы [ 6 ]

8 голосов
/ 22 марта 2011

Хорошо, я мог бы исправить это путем поиска примеров

Это работает, но может использоваться только для JSON, а не для XML

@GET
@Produces({MediaType.APPLICATION_JSON})
@Path("/get")
public JSONArray get() {;
    return new JSONArray(dao.getStringList());
}

Исправляет проблему, но естьтакже общий подход?

6 голосов
/ 22 марта 2011

Вы можете использовать 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) {};
}
1 голос
/ 24 февраля 2012

Чтобы убедить Джерси выводить списки так, как вы хотите, вам нужно предоставить собственный 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 ...

0 голосов
/ 02 февраля 2017

Моим решением для этого был класс-обёртка (где-то нашел).Это работает сейчас.Я не понимаю мысли о том, что я не поддерживаю класс List Java как корневой элемент.Возможно, это связано с некоторыми спецификациями / рекомендациями json, о которых я не знаю.

Но сейчас я использую это:

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;
    }
}
0 голосов
/ 15 августа 2014

В дополнение к предоставленным ответам, если вы все еще получаете MessageBodyWriter not found, попробуйте добавить зависимость, такую ​​как:

    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-moxy</artifactId>
    </dependency>
0 голосов
/ 11 июля 2012

Вам необходимо использовать альтернативную конфигурацию JSON JSONConfiguration.natural().

Лучше всего создать свой собственный ContextResolver, используя эту альтернативную конфигурацию в качестве провайдера, и сообщить ему, за какие классы он отвечает.

Мне неизвестен способ использовать альтернативную конфигурацию глобально другим способом.

...