How do I parse a x-www-url-encoded string into a Map[String, String] using Lift?
Asked Answered
M

4

8

From Lift, I'm getting a string of the form

TOKEN=EC%2d454178600K772032D&TIMESTAMP=2011%2d06%2d29T13%3a10%3a58Z&CORRELATIONID=cbd56e97cad38&ACK=Success&VERSION=64&BUILD=1936884

from the response of an HTTP request.

Although it's probably ultra-trivial, I can't find the Lift function that parses this into a nice Map[String, String]. Any help?

Microminiaturization answered 29/6, 2011 at 13:27 Comment(0)
L
13

From Lift's Req.scala:

// calculate the query parameters
lazy val queryStringParam:  (List[String], Map[String, List[String]]) = {
  val params: List[(String, String)] =
    for {
      queryString <- request.queryString.toList
      nameVal <- queryString.split("&").toList.map(_.trim).filter(_.length > 0)
      (name, value) <- nameVal.split("=").toList match {
        case Nil => Empty
        case n :: v :: _ => Full((urlDecode(n), urlDecode(v)))
        case n :: _ => Full((urlDecode(n), ""))
      }} yield (name, value)

        val names: List[String] = params.map(_._1).distinct
  val nvp: Map[String, List[String]] = params.foldLeft(Map[String, List[String]]()) {
    case (map, (name, value)) => map + (name -> (map.getOrElse(name, Nil) ::: List(value)))
  }

  (names, nvp)
}
Liquidambar answered 29/6, 2011 at 22:26 Comment(1)
Thank you very much David. I will then copy from this snippet.Microminiaturization
D
4

I haven't seen any Lift's implementation for that. You can achieve this with something like this:

val input = "TOKEN=EC%2d454178600K772032D&TIMESTAMP=2011%2d06%2d29T13%3a10%3a58Z&CORRELATIONID=cbd56e97cad38&ACK=Success&VERSION=64&BUILD=1936884"
val res = input.split('&') map { str =>
    val pair = str.split('=')
    (pair(0) -> pair(1))
} toMap

note: it assumes, that you have a well-formed string. In your code you should probably check if the string is ok.

Disseminule answered 29/6, 2011 at 13:41 Comment(3)
Lift does it since it parses request parameters, which are encoded in the same way. Yes, writing your own parser for that looks easy, but I want one that is well tested and also works for the corner cases. For instance, your solution should call URLEncoder.encode(_, "UTF-8") on the broken-apart strings before putting them in the map.Microminiaturization
You're probably looking for scala-tools.org/mvnsites/liftweb-2.0/framework/scaladocs/net/…Disseminule
Thanks, but actually no, since the string to parse is returned to me as a response to a request I made from my back end server (to PayPal, actually).Microminiaturization
N
0

I put together a small Scala library to help do this: https://github.com/theon/scala-uri

You can parse a uri and get the parameters into a Map[String,List[String]] like so:

val uri = parseUri("http://example.com?one=1&two=2").query.params

It also has a DSL for building URLs with query strings:

val uri = "http://example.com" ? ("one" -> 1) & ("two" -> 2)
Nighttime answered 19/11, 2012 at 22:2 Comment(0)
W
0
scala> val queryParams = "a=4&b=5"
scala> queryParams.split("&").toList.map(_.trim).filter(_.length > 0).flatMap(x => {
    val s = x.split('=')
    Map[String, String](s(0) -> s(1))
}).toMap[String, String]

res0: scala.collection.immutable.Map[String,String] = Map(a -> 4, b -> 5)
Wherein answered 6/12, 2013 at 2:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.