2011-01-29 11 views
6

que tienen un servicio web de descanso, y la respuesta es:JAX-RS - JSON sin nodo raíz

{ 
    "cities": [{ 
     "id": "1", 
     "name": "City 01", 
     "state": "A1" 
    }, { 
     "id": "2", 
     "name": "City 02", 
     "state": "A1" 
    }] 
} 

pero quiero esto:

{ 
    [{ 
     "id": "1", 
     "name": "City 01", 
     "state": "A1" 
    }, { 
     "id": "2", 
     "name": "City 02", 
     "state": "A1" 
    }] 
} 

¿Cómo puedo configurar JAX-RS a produce JSON sin nodo raíz utilizando solo la función JAX-RS, y no la función específica de implementación? Mi código debe ser portátil en cualquier servidor de aplicaciones.

+0

cómo es su modelo de JAXB (Ciudad) Clase anotado? esto es lo que controlará la serialización/deserialización hacia/desde XML y JSON. –

+0

Mi clase a continuación: @XmlRootElement (name = "cities") public class CityDTO implementa Serializable { } –

Respuesta

4

Tuve el mismo problema con Glassfish v3. Descubrí que este comportamiento depende de la implementación de JAX-RS y el cambio a la implementación de Jackson JAX-RS de Codehaus me solucionó el problema.

Si está utilizando Glassfish así, entonces se puede resolver el problema mediante la adición org.codehaus.jackson.jaxrs a su guerra, así como a la configuración WEB-INF/web.xml de la siguiente manera:

<!-- REST --> 

<servlet> 
    <servlet-name>RESTful Services</servlet-name> 
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class> 
    <init-param> 
    <param-name>com.sun.jersey.config.property.resourceConfigClass</param-name> 
    <param-value>com.sun.jersey.api.core.PackagesResourceConfig</param-value> 
    </init-param> 
    <init-param> 
    <param-name>com.sun.jersey.config.property.packages</param-name> 
    <param-value>you.service.packages;org.codehaus.jackson.jaxrs</param-value> 
    <!-- NOTE: The last element above, org.codehaus.jackson.jaxrs, replaces the default 
     JAX-RS processor with the Codehaus Jackson JAX-RS implementation. The default 
     JAX-RS processor returns top-level arrays encapsulated as child elements of a 
     single JSON object, whereas the Jackson JAX-RS implementation return an array. 
    --> 
    </init-param> 
    <load-on-startup>1</load-on-startup> 
</servlet> 

<servlet-mapping> 
    <servlet-name>RESTful Services</servlet-name> 
    <url-pattern>/your/rest/path/*</url-pattern> 
</servlet-mapping> 

Alternativamente, usted podría ser capaz de simplemente interceptar la respuesta en el cliente:

function consumesCity(json) { 
    ... 
} 

Reemplazar

... consumesCity(json) ... 

con

function preprocess(json) { 
    return json.city; 
} 

... consumesCity(preprocess(json)) ... 
+1

Gracias, Kim. Pero aún buscaré una solución portátil. –

+3

Me dio la impresión de que este comportamiento particular es específico del proveedor, es decir, si el objeto JSON de nivel superior para un tipo de devolución de colección será una matriz o un solo objeto con un campo que contiene los miembros de la colección. Estaba un poco consternado al ver que la implementación de referencia de Glassfish devuelve el último estilo para las colecciones. Creo que devolver una matriz JSON es mucho más intuitivo. Por favor, publique una actualización si encuentra una mejor solución. –

+1

Estoy de acuerdo con Kim.Si bien las estructuras realmente difieren, principalmente debido a razones históricas, y específicamente porque hay libs que manejan JSON a través de API XML, lo que a veces obliga al uso de envoltorios, en realidad no existe una manera más estándar, a menos que desee usar una función personalizada MessageBodyWriter/Implementaciones de Reader. – StaxMan

1

Buena pregunta. He tenido un requisito similar a esto. Tenía que tener acceso a la respuesta bruta generada y hacer algo de manipulación. Lo logré registrando un filtro resonse y luego adapté un respondedor personalizado. Vea el enlace a continuación para más detalles.

http://www.mentby.com/paul-sandoz/access-to-raw-xml-in-jersey.html 

En el filtro de respuesta, que podría recortar el nombre de clase de JSON generado, o mejor aún, cadena devuelta en la respuesta y utilizar el mecanismo de serialización personalizado JSON como Google-GSON.

Avísame si esta solución funciona.

0

Respuesta de Kim Burgaard arriba también funciona para Jersey Spring WS. Tuve el mismo problema al utilizar Glassfish 3.0 y lo resolví agregando el parámetro que se muestra a continuación.

Ejemplo Web.xml

<?xml version="1.0" encoding="UTF-8"?> 
<web-app version="2.4" 
     xmlns="http://java.sun.com/xml/ns/j2ee" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> 
    <context-param> 
     <param-name>contextConfigLocation</param-name> 
     <param-value>classpath:applicationContext.xml</param-value> 
    </context-param> 
    <listener> 
     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
    </listener> 
    <listener> 
     <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> 
    </listener> 
    <servlet> 
     <servlet-name>Jersey Spring Web Application</servlet-name> 
     <servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class> 
     <init-param> 
      <param-name>com.sun.jersey.config.property.packages</param-name> 
      <param-value>org.codehaus.jackson.jaxrs</param-value> 
<!--    NOTE: The last element above, org.codehaus.jackson.jaxrs, replaces the default 
       JAX-RS processor with the Codehaus Jackson JAX-RS implementation. The default 
       JAX-RS processor returns top-level arrays encapsulated as child elements of a 
       single JSON object, whereas the Jackson JAX-RS implementation return an array.--> 
     </init-param> 
    </servlet> 
    <servlet-mapping> 
     <servlet-name>Jersey Spring Web Application</servlet-name> 
     <url-pattern>/services/*</url-pattern> 
    </servlet-mapping> 
</web-app> 

Ejemplo applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" 
     xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" 
     xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" 
     xsi:schemaLocation=" 
      http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd 
      http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd 
      http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd 
      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> 
    <!-- Scan for both Jersey Rest Annotations and persistence classes --> 
    <context:component-scan base-package="your.service.packages"/> 
</beans> 
Cuestiones relacionadas