Search code examples
scalaweburlakkaurldecode

Parsing Url Parameters in Scala


I've been struggling for a while to get a neat utility function for parsing sensible parameters out of encoded URLs in Scala. Despite a lot of reading & trying with library tools I haven't anything particularly usable.

This is my current solution, using a couple of matching sets. I'd be interested in some feedback or other solutions people have for doing this.

def EncodedUrlToParamMap(encodedURL:String): Map[String,String] = {
  def toMap(l:List[String], acc: Map[String,String]): Map[String,String] = {
    if (l.length<2) acc
    else if (l.length==2) toMap( List.empty, acc + (l.head -> URLDecoder.decode(l.tail.head,"UTF-8")))
    else toMap( l.drop(2), acc+(l.head->l(2)))
  }

  val paramPattern: Regex = "\\?([\\s\\S]*)$".r
  val valuePattern: Regex = "[^?=&]*".r

  paramPattern.findFirstIn( encodedURL ) match {
    case Some(params) =>
      val values: List[String] = valuePattern.findAllIn( params ).toList.filter(_.nonEmpty)
      toMap(values, Map.empty)
    case None =>
      Map.empty
  }
}
  • paramPattern transforms "https//www.domain.com/page?key1=value1&key2=value2" --> "?key1=value1&key2=value2"
  • valuePattern separates each key & value

Solution

  • If you just want to extract the key/value, you can do that in a easier way but first, just type your string as an URI

      def EncodedUrlToParamMap2(encodedURL: URI): Map[String,String] = {
        val map = encodedURL
          .getRawQuery          //Method from URI - you get the query string directly (after the ?)
          .split("&")           //Split on "&"
          .collect {
            case s"$key=$value" => key -> value //Since scala 2.13, you can do pattern matching with extraction 
                                                // The -> creates a tuple of 2 elements
                                                // You can add URLDecoder on v here
          }
          .toMap                    // Get the whole as a Map
        map
      }
    
      val uri = new URI("https//www.domain.com/page?key1=value1&key2=value2")
      EncodedUrlToParamMap2(uri)