【问题标题】:Jersey: Json array with 1 element is serialized as object泽西岛:具有 1 个元素的 Json 数组被序列化为对象
【发布时间】:2012-11-14 13:05:36
【问题描述】:

我正在使用 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"}]}

即里面只有一个对象的数组?

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

感谢您的宝贵时间。

【问题讨论】:

    标签: java ajax json jersey


    【解决方案1】:

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

    我之前尝试过,但没有成功,因为我的项目的构建路径中没有 jackson 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>
    

    瞧!

    【讨论】:

    • 这回答了我的问题,而没有修改我的代码中的任何内容。谢谢。
    【解决方案2】:

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

    jersey official document有详细配置:

    要实现更重要的 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;
        }
    }
    

    【讨论】:

    • 添加此解析器后响应将如何格式化,所以我需要在某处告诉代码使用此解析器?
    【解决方案3】:

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

    How can I customize serialization of a list of JAXB objects to JSON?

    【讨论】:

      【解决方案4】:

      我正在使用 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>
      

      【讨论】:

      • 这显然是使用 spring 配置的唯一方法。这不是最佳选择,但就我而言,这是唯一的方法。
      【解决方案5】:

      您可以使用 Jettison(与 Jersey 一起提供)并使用 JSONObjectJSONArray 作为返回值来准备您想要的结构。 它们位于jettison-1.3.2.jar 的包org.codehaus.jettison.json 中,这是jerysey-json 的传递依赖项

      【讨论】:

      • JSONArray 类在哪里定义?我必须从 json.org 添加 json 库吗?
      【解决方案6】:

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

      【讨论】:

        【解决方案7】:

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

        在你的 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>
        

        【讨论】:

          【解决方案8】:

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

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

          @JsonFormat(with = 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;
              }
          
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-03-13
            • 2011-10-14
            • 2015-01-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-10-06
            相关资源
            最近更新 更多