27

我正在使用 Jersey/Java 创建一个 REST 服务器,但我发现了一个奇怪的行为。

我在服务器上有一个方法,它返回一个对象数组作为 Json

@GET
@Path("/files")
@Produces(MediaType.APPLICATION_JSON)
public Object getFiles() throws Exception{
    DatabaseManager db = new DatabaseManager();
    FileInfo[] result = db.getFiles();
    return result;
}

代码正确执行并将数据返回给客户端(jQuery ajax 调用)。问题是如果“结果”数组有一个或多个元素,则返回数据的格式会发生变化。

一个元素的响应:

{"fileInfo":{"fileName":"weather.arff","id":"10"}}

包含两个元素的响应:

{"fileInfo":[{"fileName":"weather.arff","id":"10"},{"fileName":"supermarket.arff","id":"11"}]}

如您所见,在第一种情况下,返回对象的“fileInfo”属性的值是一个对象,而在第二种情况下,该值是一个数组。我究竟做错了什么?第一种情况不应该返回如下内容:

{"fileInfo":[{"fileName":"weather.arff","id":"10"}]}

即一个内部有一个对象的数组?

我知道我可以在客户端检测到这一点,但这似乎是一个非常丑陋的黑客攻击。

谢谢你的时间。

4

8 回答 8

12

我最终使用了 Jackson,也在泽西官方文档 (http://jersey.java.net/nonav/documentation/latest/user-guide.html#json.pojo.approach.section) 中进行了描述。

我之前尝试过,但它不起作用,因为我的项目的构建路径中没有杰克逊 jar(根据文档,我认为它是内置到 jersey 的核心库中的)。

我刚刚添加了 jackson-all.jar 文件 (http://wiki.fasterxml.com/JacksonDownload) 并在配置中启用了 POJO 支持

    <init-param>
          <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
          <param-value>true</param-value>
    </init-param>

瞧!

于 2012-11-27T23:05:58.040 回答
5

如果您使用 JAXB 构建 JSON 结果,您可以配置 Jersey JSON 处理器以获得更重要的 JSON 格式。

jersey 官方文档有详细的配置:

要实现更重要的 JSON 格式更改,您需要配置 Jersey JSON 处理器本身。可以在 JSONConfiguration 实例上设置各种配置选项。然后可以进一步使用该实例来创建 JSONConfigurated JSONJAXBContext,作为该区域的主要配置点。要将您的专用 JSONJAXBContext 传递给 Jersey,您最终需要实现一个 JAXBContext ContextResolver:

    @Provider
public class JAXBContextResolver implements ContextResolver<JAXBContext> {
    private final JAXBContext context;
    private final Set<Class> types;
    private Class[] ctypes = { FileInfo.class}; //your pojo class
    public JAXBContextResolver() throws Exception {
        this.types = new HashSet(Arrays.asList(ctypes));
        this.context = new JSONJAXBContext(JSONConfiguration.natural().build(),
                ctypes); //json configuration
    }

    @Override
    public JAXBContext getContext(Class<?> objectType) {
        return (types.contains(objectType)) ? context : null;
    }
}
于 2012-11-27T04:42:37.473 回答
1

另请查看以下答案,它为我解决了这个问题:

如何自定义将 JAXB 对象列表序列化为 JSON?

于 2013-05-11T15:25:20.920 回答
1

我正在使用 cxf,这是我的 applicationContext.xml 在 JSON 中强制数组:

<jaxrs:server id="myService" serviceName="MyService"
address="/mysvc">
<jaxrs:serviceBeans>
    <ref bean="myServiceImpl"/>
</jaxrs:serviceBeans>
<jaxrs:providers>
    <bean class="org.apache.cxf.jaxrs.provider.json.JSONProvider">
   <property name="dropRootElement" value="true" />
   <property name="supportUnwrapped" value="true" />
   <property name="namespaceMap">
      <map>
        <entry key="http://example.com/myservice" value=""/>
      </map>
   </property>
   <property name="arrayKeys">
      <list>
    <value>fileInfo</value>
      </list>
   </property>                          
    </bean>
</jaxrs:providers>
</jaxrs:server>
于 2015-06-17T14:10:40.497 回答
0

您也可以尝试 Genson 库http://code.google.com/p/genson/。它与 jersey 很好地集成,只需将 jar 放入您的类路径中,一切都会正常工作。它不需要你编写额外的代码,它应该像你现在拥有的那样工作,但没有任何奇怪的结果。

于 2012-11-27T09:01:01.047 回答
0

您可以使用 Jettison(与 Jersey 一起提供)并准备您希望自己使用的结构JSONObjectJSONArray作为返回值。它们在包org.codehaus.jettison.json中,包的jettison-1.3.2.jar传递依赖于jerysey-json

于 2012-11-27T00:24:22.503 回答
0

我挣扎了很多,找到了这个简单的解决方案

在你的 pom.xml 中:

<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-jaxrs</artifactId>
    <version>1.9.13</version>
</dependency>
<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-xc</artifactId>
    <version>1.9.13</version>
</dependency>

在您的 web.xml 中:

<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
    <param-name>com.sun.jersey.config.property.packages</param-name>
    <param-value>com.other-packages;org.codehaus.jackson.jaxrs</param-value>
</init-param>
于 2016-06-11T06:15:47.503 回答
0

将 Array 转换为 ArrayList 就可以满足这里的要求。我遇到过类似的矛盾问题,如果是单个元素,我必须返回 Json 数组对象而不是列表。

我在下面的注释的帮助下完成了我的工作-

@JsonFormat(与 = JsonFormat.Feature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED)。下面是 JSON Pojo 类的示例:

import java.util.List;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;

@JsonIgnoreProperties(ignoreUnknown = true)
public class TAResponseMapper {

    @JsonProperty("Response")
    @JsonFormat(with = JsonFormat.Feature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED) 
    private List<TAResponse> responses;

    public List<TAResponse> getResponses() {
        return responses;
    }

    public void setResponses(List<TAResponse> responses) {
        this.responses = responses;
    }

}
于 2019-05-08T11:19:32.853 回答