1

Whats the best way to handle generics and erasure when doing pattern matching in Scala (a Map in my case). I am looking for a proper implementation without compiler warnings. I have a function that I want to return Map[Int, Seq[String]] from. Currently the code looks like:

def teams: Map[Int, Seq[String]] = {
    val dateam = new scala.collection.mutable.HashMap[Int, Seq[String]]

    // data.attributes is Map[String, Object] returned from JSON parsing (jackson-module-scala)
    val teamz = data.attributes.get("team_players")
    if (teamz.isDefined) {
      val x = teamz.get
      try {
        x match {
          case m: mutable.Map[_, _] => {
            m.foreach( kv => {
              kv._1 match {
                case teamId: String => {
                  kv._2 match {
                    case team: Seq[_] => {
                      val tid: Int = teamId.toInt
                      dateam.put(tid, team.map(s => s.toString))
                    }
                  }
                }
              }
            })
          }
        }
      } catch {
        case e: Exception => {
          logger.error("Unable to convert the team_players (%s) attribute.".format(x), e)
        }
      }

      dateam
    } else {
      logger.warn("Missing team_players attribute in: %s".format(data.attributes))
    }
    dateam.toMap
}
4
  • Please add the compiler warnings that this code generates. Commented Dec 16, 2013 at 9:08
  • 2
    Same code after a little refactoring. Commented Dec 16, 2013 at 9:25
  • 2
    A lot of context is necessary here -- first off, what exactly are you trying to accomplish? You're only "pattern matching" with one case, so the intent isn't clear. What errors are you getting and for what inputs? Commented Dec 16, 2013 at 11:36
  • I have some JSON data that I know is Map[Int, Seq[String]]. Unfortunately from the Jackson library I get Map[String, Object], so I was looking for some sort of casting :) Commented Dec 18, 2013 at 13:54

2 Answers 2

2

Use a Scala library to handle it. There are some based on Jackson (Play's ScalaJson, for instance -- see this article on using it stand-alone), as well as libraries not based on Jackson (of which my preferred is Argonaut, though you could also go with Spray-Json).

These libraries, and others, solve this problem. Doing it by hand is awkward and prone to errors, so don't do it.

Sign up to request clarification or add additional context in comments.

Comments

1

It could be reasonable to use for comprehension (with some built in pattern matching). Also we could take into account that Map is a list of tuples, in our case of (String, Object) type. As well we will ignore for this example probable exceptions, so:

import scala.collection.mutable.HashMap

def convert(json: Map[String, Object]): HashMap[Int, Seq[String]] = {

  val converted = for {
    (id: String, description: Seq[Any]) <- json
  } yield (id.toInt, description.map(_.toString))

  HashMap[Int, Seq[String]](converted.toSeq: _*)
}

So, our for comprehension taking into account only tuples with (String, Seq[Any]) type, then combines converted String to Int and Seq[Any] to Seq[String]. And makes Map to be mutable.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.