泽西岛:返回一个字符串列表

时间:2011-03-22 13:57:37

标签: java rest jersey jax-rs

我尝试将Jersey中的字符串列表作为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 

然后我为List

编写了一个包装器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 个答案:

答案 0 :(得分:8)

好的,我可以通过搜索样本来修复它

这确实有效,但它只能用于JSON而不能用于XML

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

修复问题,但是还有一种通用方法吗?

答案 1 :(得分:6)

您可以使用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 :(得分:1)

为了说服泽西按照你想要的方式输出列表,你需要提供一个自己的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中添加该类......

答案 3 :(得分:0)

您需要使用备用JSON配置JSONConfiguration.natural()

最好使用该备用配置作为提供程序创建自己的ContextResolver,并告诉它负责哪些类。

我不知道以另一种方式全局使用替代配置的方法。

答案 4 :(得分:0)

除了提供的答案之外,如果您仍然获得MessageBodyWriter not found,请尝试添加依赖项,例如:

    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-moxy</artifactId>
    </dependency>

答案 5 :(得分:0)

我对此的解决方案是一个包装类(在某处找到它)。它现在有效。我不理解不支持javas List类作为根元素的想法。也许它与我不知道的一些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;
    }
}