2013-08-02 12 views
8

Ecco un servizio Jersey:Jersey. Come generare JSON e output XML a seconda url param

@GET 
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) 
public Response service(@QueryParam("format") String format) { 

    if (format.equals("json")) {...} 

    return response; 

} 

voglio generare XML o JSON risposta indietro a seconda url param "formato".

mio risposta esempio si sta formando dal jaxb2

So che può ottenere xml o json risposta indietro se sul mio client Java test/functional utilizzando questo codice:

String content = service.path("").queryParam("myparam", "myvalue").accept(MediaType.APPLICATION_XML).get(String.class); 

o

String content = service.path("").queryParam("myparam", "myvalue").accept(MediaType.APPLICATION_JSON).get(String.class); 

Ma ho bisogno di farlo in base al parametro url.

+0

Se si potesse inviare un corretto parametro 'ContentType',' application/json' invece di 'json', allora si potrebbe utilizzare' MediaType.valueOf (formato) 'per ottenere l'istanza' MediaType' e usalo con il metodo accept. –

+2

Il problema è che non si sa come impostare il tipo di contenuto della risposta o ...? – DannyMo

risposta

4

È possibile impostare il tipo di supporto di entità risposta direttamente via Response#ok (supponendo che si desidera tornare HTTP 200 stato) Metodo

@GET 
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) 
public Response service(@QueryParam("format") String format) { 
    return Response 
      // Set the status, entity and media type of the response. 
      .ok(entity, "json".equals(format) ? MediaType.APPLICATION_JSON : MediaType.APPLICATION_XML) 
      .build(); 
} 

o utilizzando il metodo Response.ResponseBuilder#header

@GET 
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) 
public Response service(@QueryParam("format") String format) { 
    return Response 
      // Set the status and Put your entity here. 
      .ok(entity) 
      // Add the Content-Type header to tell Jersey which format it should marshall the entity into. 
      .header(HttpHeaders.CONTENT_TYPE, "json".equals(format) ? MediaType.APPLICATION_JSON : MediaType.APPLICATION_XML) 
      .build(); 
} 
0

Ok. Dal momento che stiamo parlando di cose al di fuori del modello qui lasciatemi provare qualcosa:

Che ne dici di utilizzare un filtro (cercare com.sun.jersey.spi.container.ResourceFilterFactory) sul tuo servizio e modificare (o aggiungere o sovrascrivere) l'intestazione di accettazione in base alla query param?

Non l'approccio più onesto, l'ammetto, ma penso che si dovrebbe fare un tentativo

10

Questo non è il modo corretto di fare ciò che si wan t. Non dovresti utilizzare un parametro di query per determinare il formato di output. Hai dichiarato che il tuo metodo di risorsa produce sia XML che JSON, il modo conforme allo standard è di consentire al client di inviare un'intestazione HTTP "Accetta" appropriata che dichiari quali tipi di media sono in grado di utilizzare. Se inviano "Accept: application/json", l'implementazione JAX-RS deve scegliere di formattare la risposta del metodo come JSON, se il client invia "Accept: application/xml", dovrebbe formattare automaticamente la risposta come XML. Se il client indica che possono accettare entrambi, la tua implementazione JAX-RS è libera di scegliere e non ti importa. Se il client indica che non possono accettarli, il tuo JAX-RS dovrebbe restituire un appropriato codice di errore HTTP che indica che non hanno un modo per inviare una risposta adeguata.

+0

Potrei perdere smth/ma che "questo non è il modo giusto" non è completamente corretto. Cosa succede se, ad esempio, desidera creare un servizio OData? È anche all'interno dello standard che deve avere un parametro di query $ format per selezionare il formato di output. –

+0

Non sapevo nulla di OData finché non ho visto la tua risposta, non l'ho mai usata. Ho basato la mia risposta su ciò che sapevo dei principi REST in quel momento. Prenderò la tua parola che OData fa questo, ma non sembra corretto, in quanto si suppone che il REST sia basato sull'utilizzo degli standard HTTP, e determinare il formato di output da un parametro di query non è alcun tipo di standard HTTP che io conosca. – user2456600

1

Qui l'esempio completo, la risposta sopra è giusta. Uso anche l'approccio sopra, ma affronta problemi mentre lavoro con List. Ho impostato l'entità in questo modo:

public Response getCoursesJSONOrXML(@QueryParam("type") String type){ 
    //Here we get list 
    List<Course> entity= courseService.getAllCourses(); 
    Response response = Response 
      .ok(entity, "xml".equals(type) ? MediaType.APPLICATION_XML : MediaType.APPLICATION_JSON) 
      .build(); 
    return response; 
} 

Dopo che sto affrontando questa eccezione:

MessageBodyWriter not found for media type=application/json, type=class java.util.Arrays$ArrayList, genericType=class java.util.Arrays$ArrayList 

Dopo aver letto il documento jersey, ho trovato la soluzione che abbiamo bisogno di usare GenericEntity per il nostro corso elenco.Qui l'esempio

@GET 
@Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML}) 
public Response getCoursesJSONOrXML(@QueryParam("type") String type){ 
    //Here we get list 
    List<Course> list = courseService.getAllCourses(); 
    GenericEntity<List<Course>> entity = new GenericEntity<List<Course>>(list) {}; 
    Response response = Response 
      .ok(entity, "xml".equals(type) ? MediaType.APPLICATION_XML : MediaType.APPLICATION_JSON) 
      .build(); 
    return response; 
}