首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在Scala中使用标准的Scala类解析JSON?

如何在Scala中使用标准的Scala类解析JSON?
EN

Stack Overflow用户
提问于 2010-11-13 12:18:52
回答 7查看 145.8K关注 0票数 115

我正在使用Scala2.8中的build in JSON类来解析JSON代码。我不想使用Liftweb one或任何其他的,因为最小化了依赖性。

我这样做似乎太刻不容缓了,有没有更好的方法呢?

代码语言:javascript
复制
import scala.util.parsing.json._
...
val json:Option[Any] = JSON.parseFull(jsonString)
val map:Map[String,Any] = json.get.asInstanceOf[Map[String, Any]]
val languages:List[Any] = map.get("languages").get.asInstanceOf[List[Any]]
languages.foreach( langMap => {
val language:Map[String,Any] = langMap.asInstanceOf[Map[String,Any]]
val name:String = language.get("name").get.asInstanceOf[String]
val isActive:Boolean = language.get("is_active").get.asInstanceOf[Boolean]
val completeness:Double = language.get("completeness").get.asInstanceOf[Double]
}
EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2010-11-15 23:50:29

这是一个基于提取器的解决方案,它将执行类类型转换:

代码语言:javascript
复制
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
        }]
      }
    """.stripMargin

val 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)))

在for循环开始时,我人为地将结果包装在一个列表中,以便在结束时生成一个列表。然后,在for循环的其余部分中,我使用生成器(使用<-)和值定义(使用=)将使用unapply方法这一事实。

(较旧的答案被编辑掉了-如果你好奇,请检查编辑历史)

票数 133
EN

Stack Overflow用户

发布于 2013-06-03 06:20:43

这是我进行模式匹配的方法:

代码语言:javascript
复制
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)
}
票数 22
EN

Stack Overflow用户

发布于 2013-09-06 03:16:50

我喜欢@huynhjl的回答,它引导我走上了正确的道路。然而,它并不擅长处理错误条件。如果所需的节点不存在,则会出现强制转换异常。我稍微调整了一下,以便利用Option更好地处理这个问题。

代码语言:javascript
复制
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)
}

当然,这与其说是处理错误,不如说是避免错误。如果缺少任何json节点,这将产生一个空列表。您可以在执行操作之前使用match检查节点的存在...

代码语言:javascript
复制
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"
  }
}
票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4170949

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档