1

I'm frequently finding myself doing something like:

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

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

whereas what I'd much prefer to write is:

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

but get doesn't take type parameters -- so my code is overly verbose as follows:

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

How can I simplify access to containers in situations like this? (In the case of JSON-style objects I'm doing this a LOT)

Robin Green
  • 32,079
  • 16
  • 104
  • 187
user48956
  • 14,850
  • 19
  • 93
  • 154
  • 2
    `(null: Object).asInstanceOf[String]` works just fine. Also note that `get` on `Map` returns `Option[T]`, in this case `Option[Any]` and it is never `null`. It could be `Some(null)`, but not `null`. – senia Jan 21 '14 at 19:31
  • 2
    Not an answer, but there are much, much nicer ways to handle JSON in Scala that don't involve `Map[String, Any]`—see for example my answer [here](http://stackoverflow.com/a/20029818/334519). – Travis Brown Jan 21 '14 at 20:07
  • @senia -- quite right. Have modified the question. – user48956 Jan 21 '14 at 22:20

1 Answers1

1

It can be easily achieved using implicits:

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

But beware, asInstance on null for value types (Int, Double, etc) produces zero values (but you can easily modify the method to fit your requirements).

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
dmitry
  • 4,989
  • 5
  • 48
  • 72
  • How efficient is this? Is a new object created for each call to gett? – user48956 Jan 21 '14 at 22:25
  • Actially this is done in compile time and basically gets translated to `gett(m, k)`. No new instance is created, as I recall. You may want to read http://stackoverflow.com/questions/6381940/what-is-the-performance-impact-of-scala-implicit-type-conversions – dmitry Jan 22 '14 at 08:36