2016-04-12 1 views
1

Je souhaite accéder à certains paramètres de requête pour toutes mes demandes. Une requête exemple serait quelque chose comme:Paramètre de requête en tant que liste

http://api.mysite.com/accounts/123?include=friends,photos 

Là où je veux avoir accès à la liste des séparées par des virgules include relations.


Pour autant que je sache, ce qui suit ne fonctionne pas et se penchera sur la liste d'inclusion comme une seule chaîne:

// routes.txt 
GET /accounts/:id controllers.AccountsController.get(id: Int, include: Seq[String]) 

Voilà comment je suis en train de faire ce , mais j'espérais qu'il y avait une façon plus propre.

// routes.txt 
GET /accounts/:id controllers.AccountsController.get(id: Int, include: Option[String]) 

// AccountsController.scala 
def get(id: Int, include: Option[String]) = Action { 

    // Convert the option to a set 
    val set = if (include.isDefined) include.get.split(",").toSet else Set() 

} 

Répondre

3

La bonne façon de le faire (déjà pris en charge par Play) serait d'utiliser des valeurs clés répétées dans la chaîne de requête, à savoir:

http://api.mysite.com/accounts/123?include=friends&include=photos 

qui lierait automatiquement Seq("friends", "photos") à include dans ce route. Cela présente l'avantage de pouvoir utiliser des virgules dans les clés et est cohérent avec l'utilisation courante des paramètres de chaîne de requête.

Vous pouvez également créer un QueryStringBindable[List[String]] personnalisé pouvant gérer une liste séparée par des virgules. Quelque chose comme:

object QueryStringBinders { 

    implicit def listBinder(key: String)(implicit stringBinder: QueryStringBindable[String]) = { 
     new QueryStringBindable[List[String]] { 
      override def bind(key: String, params: Map[String, Seq[String]]): Option[Either[String, List[String]]] = 
       stringBinder.bind(key, params).map(_.right.map(_.split(",").toList)) 

      override def unbind(key: String, strings: List[String]): String = 
       s"""$key=${strings.mkString(",")}""" 

     } 
    } 

} 

Ensuite, vous utiliseriez PlayKeys.routesImport += "QueryStringBinders._" dans les build.sbt à l'utiliser (ou quel que soit le nom du package complet est). L'utilisation d'un QueryStringBindable rendrait la logique de split réutilisable, avec un minimum de standard.

0

Comme, @mz dit la bonne façon d'utiliser est répétée des valeurs-clés dans la chaîne de requête comme: http://api.mysite.com/accounts/123?include=friends&include=photos

et vous l'action, vous pouvez accéder à la chaîne de requête avec la méthode queryString ainsi-à-dire

votre itinéraire ressemblera à ceci:

GET /accounts/:id controllers.AccountsController.get(id: Int) 

et dans votre contrôleur:

// AccountsController.scala 

    def get(id: Int) = Action { request => 

     // the `request.queryString` will give you Map[String, Seq[String]] i.e all they keys and their values 

     val includes = request.queryString.getOrElse("include", Nil) 
    }