Краткий способ опустить содержимое контейнера

Я часто ловлю себя на том, что делаю что-то вроде:

val json:Map[String,Any] = getJSON(...)

val v = json.get("username")
val uname = if ( v!=null ) v.asInstanceOf[toString] ) else null

тогда как я бы предпочел написать:

val uname = json.get[String]("username")

но get не принимает параметры типа, поэтому мой код слишком многословен:

val uname = json.get("username").asInstanceOf[String]

Как упростить доступ к контейнерам в подобных ситуациях? (В случае объектов в стиле JSON я делаю это МНОГО)


person user48956    schedule 21.01.2014    source источник
comment
(null: Object).asInstanceOf[String] работает нормально. Также обратите внимание, что get на Map возвращает Option[T], в данном случае Option[Any] и никогда не null. Это может быть Some(null), но не null.   -  person senia    schedule 21.01.2014
comment
Не ответ, но есть гораздо более приятные способы обработки JSON в Scala, которые не включают Map[String, Any] — см., например, мой ответ здесь .   -  person Travis Brown    schedule 22.01.2014
comment
@senia -- совершенно верно. Изменил вопрос.   -  person user48956    schedule 22.01.2014


Ответы (1)


Этого легко добиться с помощью implicits:

implicit class MapWGet(m: Map[String, Any]) {
  // something like this
  def gett[T](k: String): T = m(k).asInstanceOf[T]
}

Но будьте осторожны, asInstance на null для типов значений (Int, Double и т. д.) дает нулевые значения (но вы можете легко изменить метод в соответствии со своими требованиями).

scala> val json: Map[String, Any] = Map("s" -> "String", "i" -> 1, "n" -> null, "d" -> 0.10D)
json: Map[String,Any] = Map(s -> String, i -> 1, n -> null, d -> 0.1)

scala> json.gett[String]("s")
res0: String = String

scala> json.gett[String]("n")
res1: String = null

scala> json.gett[Int]("n")
res2: Int = 0

scala> json.gett[Double]("d")
res3: Double = 0.1

scala> json.gett[Int]("i")
res4: Int = 1
person dmitry    schedule 21.01.2014
comment
Насколько это эффективно? Создается ли новый объект для каждого вызова gett? - person user48956; 22.01.2014
comment
На самом деле это делается во время компиляции и в основном транслируется в gett(m, k). Насколько я помню, новый экземпляр не создается. Вы можете прочитать stackoverflow.com/questions/6381940/ - person dmitry; 22.01.2014