2012-05-20 8 views
11

c'è un buono o un modo corretto per rendere l'output in Play Framework in base a un parametro? Esempio:Formato di output di rendering (HTML, JSON, XML) in base al parametro?

Per HTML:

http://localhost:9000/user/get/5?v=HTML // should render HTML template 

Per JSON:

http://localhost:9000/user/get/5?v=JSON // should render JSON template 

penso che una richiesta intercettore potrebbe avere la capacità di raggiungere questo obiettivo, ma non ho idea di come per iniziare o da dove cominciare :-(

O forse, scrivere un generale render method che legge i parametri e l'output come richiesto, ma questo mi sembra eccessivo?

risposta

20

Se /user/5?v=html e /user/5?v=json ritorno due rappresentazioni della stessa risorsa, dovrebbero essere lo stesso URL, per esempio /user/5, in base allo REST principles.

Sul lato client, è possibile utilizzare l'intestazione Accept nelle richieste per indicare quale rappresentazione si desidera che il server invii.

Sul lato server, è possibile scrivere il seguente con Play 2.1 per testare il valore dell'intestazione Accept:

public static Result user(Long id) { 

    User user = User.find.byId(id); 
    if (user == null) { 
    return notFound(); 
    } 

    if (request().accepts("text/html")) { 
    return ok(views.html.user(user)); 
    } else if (request().accepts("application/json")) { 
    return ok(Json.toJson(user)); 
    } else { 
    return badRequest(); 
    } 
} 

Nota che il test contro "text/html" deve sempre essere scritto prima di qualsiasi altro tipo di contenuto perché i browser imposta l'intestazione Accept delle loro richieste allo */* che corrisponde a tutti i tipi.

Se non si desidera scrivere lo if (request().accepts(…)) in ogni azione, è possibile scomporlo, ad es. come la seguente:

public static Result user(Long id) { 
    User user = User.find.byId(id); 
    return representation(user, views.html.user.ref); 
} 

public static Result users() { 
    List<User> users = User.find.all(); 
    return representation(users, views.html.users.ref); 
} 

private <T> Result representation(T resource, Template1<T, Html> html) { 
    if (resource == null) { 
    return notFound(); 
    } 

    if (request().accepts("text/html")) { 
    return ok(html.apply(resource)); 
    } else if (request().accepts("application/json")) { 
    return ok(Json.toJson(resource)); 
    } else { 
    return badRequest(); 
    } 
} 
+0

ok, penso che mi piacerebbe questo più. Ma per quanto riguarda il binding agli oggetti Java basati su HTML Form o JSON Object (dalle richieste), dovrei anche implementarli con un'istruzione if/else? Oppure 'bindFromRequest' servirà entrambi? – adis

+0

'bindFromRequest' utilizza la stringa di query e il corpo della richiesta (che può essere JSON, modulo url codificato, ecc.). –

2

scrittura 2 metodi, utilizzare 2 percorsi (come non si specifica userò campioni Java:

public static Result userAsHtml(Long id) { 
    return ok(someView.render(User.find.byId(id))); 
} 

public static Result userAsJson(Long id) { 
    return play.libs.Json.toJson(User.find.byId(id)); 
} 

percorsi:

/GET /user/get/:id/html  controllers.YourController.userAsHtml(id:Long) 
/GET /user/get/:id/json  controllers.YourController.userAsJson(id:Long) 

potrai solo fare un collegamento in altra vista per visualizzare i dati degli utenti

<a href="@routes.YourController.userAsHtml(user.id)">Show details</a> 
<a href="@routes.YourController.userAsJson(user.id)">Get JSON</a> 

o qualcos'altro ...

edit # 1

si può anche usare il buon if o case per determinare l'output finale

public static Result userAsV() { 
    String vType = form().bindFromRequest().get("v"); 

    if (vTtype.equals("HTML")){ 
     return ok(someView.render(User.find.byId(id))); 
    } 

    return play.libs.Json.toJson(User.find.byId(id)); 
} 
+0

Questo potrebbe funzionare, ma duplicazione roba non sarebbe la mia prima scelta. Non ho un caso di utilizzo diretto per questo, ma in futuro, se mi piacerebbe creare un'applicazione mobile nativa, mi piacerebbe fare il reqeust per recuperare semplicemente JSON ... – adis

+0

Bene, come si desidera, controllare ** edit # 1 * * – biesior

0

ho voluto che l'utente sia in grado di essere visualizzate nel browser in formato HTML o come JSON in modo che il accetta metodo non ha funzionato per me.

ho risolto mettendo un renderMethod generica in una classe di base con la seguente sintassi stile

public static Result requestType() 
{ 
    if(request().uri().indexOf("json") != -1) 
    { 
     return ok(Json.toJson(request())); 
    } 
    else 
    { 
     return ok("Got HTML request " + request()); 
    } 
}