将查询字符串转换为 scala 中的映射

Convert query string to map in scala

我有一个这种形式的查询字符串:

val query = "key1=val1&key2=val2&key3=val3

我想用上面的 key/value 对创建一个地图。到目前为止,我是这样做的:

//creating an iterator with 2 values in each group. Each index consists of a key/value pair
val pairs = query.split("&|=").grouped(2)

//inserting the key/value pairs into a map
val map = pairs.map { case Array(k, v) => k -> v }.toMap

像我这样做有什么问题吗?如果是这样,有没有我可以用来做的库?

这是一种使用 URLEncodedUtils 的方法:

import java.net.URI

import org.apache.http.client.utils.URLEncodedUtils
import org.apache.http.{NameValuePair => ApacheNameValuePair}

import scala.collection.JavaConverters._
import scala.collection.immutable.Seq

object GetEncodingTest extends App {
  val url = "?one=1&two=2&three=3&three=3a"
  val params = URLEncodedUtils.parse(new URI(url), "UTF_8")

  val convertedParams: Seq[ApacheNameValuePair] = collection.immutable.Seq(params.asScala: _*)
  val scalaParams: Seq[(String, String)] = convertedParams.map(pair => pair.getName -> pair.getValue)
  val paramsMap: Map[String, String] = scalaParams.toMap
  paramsMap.foreach(println)
}

假设您正在使用的查询字符串如您所展示的那样简单,使用 grouped(2) 是一个很好的见解,并提供了一个非常优雅的解决方案。

下一步是使用 under-documented Array::toMap 方法:

val qs = "key=value&foo=bar"
qs.split("&|=")              // Array(key, value, foo, bar)
  .grouped(2)                // <iterator>
  .map(a => (a(0), a(1)))    // <iterator>
  .toMap                     // Map(key -> value, foo -> bar)

grouped(2) returns 和 Iterator[Array[String]],这有点难理解,因为迭代器在 Scala 控制台上不能很好地序列化。

这是相同的结果,但多了一点step-by-step:

val qs = "key=value&foo=bar"
qs.split("&")                                      // Array(key=value, foo=bar)
  .map(kv => (kv.split("=")(0), kv.split("=")(1))) // Array((key,value), (foo,bar))
  .toMap                                           // Map(key -> value, foo -> bar)

如果您想要更通用的 HTTP 查询字符串解决方案,请考虑使用库进行 URL 解析。