Java Jersey:返回字符串列表

Java Jersey:返回字符串列表,java,rest,jersey,jax-rs,Java,Rest,Jersey,Jax Rs,我尝试以JSON和XML的形式返回Jersey中的字符串列表。 我认为这是微不足道的 我的第一次尝试是写这样的东西 @GET @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) @Path("/bar") public List<String> get() { return dao.get(); } 这对于项目多于1的列表非常有效 {"data":["foo","bar"]} 不幸的是,对于

我尝试以JSON和XML的形式返回Jersey中的字符串列表。 我认为这是微不足道的

我的第一次尝试是写这样的东西

@GET
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Path("/bar")
public List<String> get() {
    return dao.get();
}
这对于项目多于1的列表非常有效

{"data":["foo","bar"]}
不幸的是,对于一个或零个元素,我得到了两个未预期的结果

{"data": "just one"} // for one element i would expect {"data": ["just one"]}

null // for no elements i would expect {"data": []}
我做错什么了吗?
我如何解决这个问题?

好的,我可以通过搜索样本来解决

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

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

修复了问题,但是否还有通用方法?

您可以使用
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) {};
}
@GET
@产生({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
@路径(“/foo”)
公共通用实体字符串列表()
{
List=Arrays.asList(“test”、“as”);
返回新的泛型实体(列表){};
}

为了说服Jersey以您想要的方式输出列表,您需要提供自己的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;
    }
}
@Provider
公共类JaxbContentResolver实现ContextResolver{
私有日志Log=LogFactory.getLog(getClass());
私有JAXBContext上下文;
公共JaxbContentResolver()抛出JAXBEException{
类[]类型={StringList.Class};
context=newjsonjaxbcontext(JSONConfiguration.mapped().rootUnwrapping(true).数组(“数据”).build(),类型);
}
@凌驾
公共JAXBContext getContext(类objectType){
trace(“为类型:“+objectType.getSimpleName()”输入测试getContext);
返回上下文;
}
}
此方式列表将按您希望的方式显示


注意:这种方法的一个缺点是您需要在代码中额外维护一个点;如果您想向REST接口添加另一个(列表包装器)类,您需要记住转到上面的代码并将该类添加到您的ContextResolver…

您需要使用可选的JSON配置
JSONConfiguration.natural()

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


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

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

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

org.glassfish.jersey.media
泽西媒体公司

我的解决方案是一个包装器类(在某处找到了它)。现在可以了。我不理解不支持javaslist类作为根元素背后的想法。也许这与我不知道的一些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;
    }
}
公共类房屋{
私人上市公司;
//泽西岛需要
公共场所({}
公共房屋(列表房屋){
这个房子=房子;
}
公共房屋(列表房屋){
这个房子=房子;
}
公众名单{
归还这所房子;
}
}

这与特定的表示形式有关,因此这是一个极为低劣的解决方案。有人有过这种方法的运气吗?我在上面的代码中看到了相同的异常…我看到了与John McCann提到的相同的异常,这种方法似乎遗漏了一些东西,这种方法不起作用。“未找到Java类javax.ws.rs.core.GenericeEntity和Java类型类javax.ws.rs.core.GenericeEntity以及MIME媒体类型应用程序/json的消息正文读取器”消息无法与Jersey 2.0 n tomcat 7一起使用,获取
说明服务器遇到内部错误,无法满足此请求。
不确定为什么这是可接受的答案。它不起作用。汤姆卡特7号,泽西岛2号,莫西
@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;
    }
}
    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-moxy</artifactId>
    </dependency>
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;
    }
}