How to parse JSON in Scala using standard Scala classes? How to parse JSON in Scala using standard Scala classes? json json

How to parse JSON in Scala using standard Scala classes?


This is a solution based on extractors which will do the class cast:

class CC[T] { def unapply(a:Any):Option[T] = Some(a.asInstanceOf[T]) }object M extends CC[Map[String, Any]]object L extends CC[List[Any]]object S extends CC[String]object D extends CC[Double]object B extends CC[Boolean]val jsonString =    """      {        "languages": [{            "name": "English",            "is_active": true,            "completeness": 2.5        }, {            "name": "Latin",            "is_active": false,            "completeness": 0.9        }]      }    """.stripMarginval result = for {    Some(M(map)) <- List(JSON.parseFull(jsonString))    L(languages) = map("languages")    M(language) <- languages    S(name) = language("name")    B(active) = language("is_active")    D(completeness) = language("completeness")} yield {    (name, active, completeness)}assert( result == List(("English",true,2.5), ("Latin",false,0.9)))

At the start of the for loop I artificially wrap the result in a list so that it yields a list at the end. Then in the rest of the for loop I use the fact that generators (using <-) and value definitions (using =) will make use of the unapply methods.

(Older answer edited away - check edit history if you're curious)


This is the way I do the pattern match:

val result = JSON.parseFull(jsonStr)result match {  // Matches if jsonStr is valid JSON and represents a Map of Strings to Any  case Some(map: Map[String, Any]) => println(map)  case None => println("Parsing failed")  case other => println("Unknown data structure: " + other)}


I like @huynhjl's answer, it led me down the right path. However, it isn't great at handling error conditions. If the desired node does not exist, you get a cast exception. I've adapted this slightly to make use of Option to better handle this.

class CC[T] {  def unapply(a:Option[Any]):Option[T] = if (a.isEmpty) {    None  } else {    Some(a.get.asInstanceOf[T])  }}object M extends CC[Map[String, Any]]object L extends CC[List[Any]]object S extends CC[String]object D extends CC[Double]object B extends CC[Boolean]for {  M(map) <- List(JSON.parseFull(jsonString))  L(languages) = map.get("languages")  language <- languages  M(lang) = Some(language)  S(name) = lang.get("name")  B(active) = lang.get("is_active")  D(completeness) = lang.get("completeness")} yield {  (name, active, completeness)}

Of course, this doesn't handle errors so much as avoid them. This will yield an empty list if any of the json nodes are missing. You can use a match to check for the presence of a node before acting...

for {  M(map) <- Some(JSON.parseFull(jsonString))} yield {  map.get("languages") match {    case L(languages) => {      for {        language <- languages        M(lang) = Some(language)        S(name) = lang.get("name")        B(active) = lang.get("is_active")        D(completeness) = lang.get("completeness")      } yield {        (name, active, completeness)      }            }    case None => "bad json"  }}