2011-01-29 11 views
6

Ho un servizio web riposante, e la risposta è:JAX-RS - JSON senza nodo principale

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

Ma voglio questo:

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

Come posso configurare JAX-RS a produce JSON senza nodo root usando solo la caratteristica JAX-RS, e non la caratteristica specifica dell'implementazione? Il mio codice deve essere trasferibile su qualsiasi appserver.

+0

come è il tuo modello (Città) classe JAXB annotato? questo è ciò che controllerà la serial/deserialization da/a XML e JSON. –

+0

La mia classe seguente: @XmlRootElement (name = "cities") public class CityDTO implementazioni serializzabile { } –

risposta

4

Ho avuto lo stesso problema con Glassfish v3. Ho scoperto che questo comportamento dipende dall'implementazione JAX-RS e il passaggio a Codehaus "L'implementazione Jackson JAX-RS ha risolto il problema per me.

Se stai usando Glassfish così, allora è possibile risolvere il problema aggiungendo org.codehaus.jackson.jaxrs alla guerra, così come per la configurazione WEB-INF/web.xml come segue:

<!-- 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> 

In alternativa, si potrebbe essere in grado di semplicemente intercettare la risposta nel client:

function consumesCity(json) { 
    ... 
} 

Sostituire

... consumesCity(json) ... 

con

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

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

Grazie, Kim. Ma cercherò ancora una soluzione portatile. –

+3

Ho l'impressione che questo particolare comportamento sia specifico del fornitore, vale a dire se l'oggetto JSON di primo livello per un tipo di ritorno alla raccolta sarà un array o un singolo oggetto con un campo che contiene i membri della raccolta. Ero un po 'scoraggiato nel vedere che l'implementazione di riferimento di Glassfish restituisce il secondo stile per le collezioni. Penso che restituire un array JSON sia molto più intuitivo. Si prega di inviare un aggiornamento se si trova una soluzione migliore. –

+1

Sono d'accordo con Kim.Mentre le strutture effettivamente differiscono - per lo più a causa di ragioni storiche, e in particolare perché ci sono librerie che gestiscono JSON tramite API XML, che a volte impongono l'uso di wrapper - non c'è davvero un modo più standard, a meno che non si voglia usare custom Implementazioni di MessageBodyWriter/Reader. – StaxMan

1

Buona domanda. Ho avuto un requisito simile a questo. Dovevo avere accesso alla risposta grezza generata e fare qualche manipolazione. L'ho raggiunto registrando un filtro di risposta e quindi adattando una riorganizzazione personalizzata. Vedi il collegamento sotto per maggiori dettagli.

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

nel filtro risposta, si poteva ritagliare il nome della classe da JSON generato, o meglio ancora, tornare stringa in risposta e utilizzare meccanismo di serializzazione JSON personalizzato come Google-GSON.

Fammi sapere se questa soluzione funziona.

0

La risposta di Kim Burgaard sopra funziona anche per Jersey Spring WS. Ho avuto lo stesso problema con Glassfish 3.0 e ho risolto aggiungendo il parametro mostrato di seguito.

Esempio 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> 

Esempio 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> 
Problemi correlati