Skip to content

Instantly share code, notes, and snippets.

@f7o
Last active June 20, 2016 07:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save f7o/b8ec553f020c54d336bab4483002776b to your computer and use it in GitHub Desktop.
Save f7o/b8ec553f020c54d336bab4483002776b to your computer and use it in GitHub Desktop.
QueryStringBindable for Map[String, String] and Map[String, List[String]]
import play.api.mvc.QueryStringBindable
import play.api.mvc.{Action, Controller}
/**
* Created by flo on 6/19/2016.
*/
object Binders {
implicit def queryMapBinder(implicit stringBinder: QueryStringBindable[String]) = new QueryStringBindable[Map[String, String]] {
override def bind(key: String, params: Map[String, Seq[String]]): Option[Either[String, Map[String, String]]] = {
val data = for {
(k, ps) <- params
if k startsWith key
p <- ps
} yield (k.drop(key.length + 1), p)
if (data.isEmpty) {
None
} else {
Some(Right(data))
}
}
override def unbind(key: String, map: Map[String, String]): String = {
map.map(x => stringBinder.unbind(s"${key}.${x._1}", x._2)).foldLeft("")((a, b) => a + b + "&")
}
override def javascriptUnbind() =
s"""function(k,v) {\n
var res = "";\n
v.forEach(function(entry) {\n
res += encodeURIComponent(k+'.'+entry.key)+'='+entry.data+'&';\n
});\n
return res;\n
}"""
}
implicit def queryMapListBinder(implicit stringBinder: QueryStringBindable[String]) = new QueryStringBindable[Map[String, List[String]]] {
override def bind(key: String, params: Map[String, Seq[String]]): Option[Either[String, Map[String, List[String]]]] = {
val data = for {
(k, ps) <- params
if k startsWith key
p <- ps
} yield (k.drop(key.length + 1), p.split(',').toList)
if (data.isEmpty) {
None
} else {
Some(Right(data))
}
}
override def unbind(key: String, map: Map[String, List[String]]): String = {
map.map(x => stringBinder.unbind(s"${key}.${x._1}", x._2.foldLeft("")((a,b) => a + b + ','))).foldLeft("")((a, b) => a + b + "&")
}
override def javascriptUnbind() =
s"""function(k,v) {\n
var res = "";\n
v.forEach(function(entry) {\n
var data = "";\n
entry.data.forEach(function(x) {\n
data += x + ',';\n
});\n
res += encodeURIComponent(k+'.'+entry.key)+'='+data.substr(0,data.length-1)+'&';\n
});\n
res.substr(0,res.length-1);\n
return res;\n
}"""
}
}
// --- Usage
object Application extends Controller {
/* Example of request the action:
* http://localhost:9000/?map.a=val1&map.b=val2&mapList.a=1,2,3&mapList.b=4,5,6
*/
def index(map: Map[String,String], mapList: Map[String,List[String]]) = Action {
Ok(views.html.index(map, mapList))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment