3

我已经阅读了其他 Scala JSON 解析问题,但它们似乎都假设一个非常基本的文档,没有深度嵌套或混合类型。或者他们假设您知道文档的所有成员,或者某些成员永远不会丢失。

我目前正在使用 Jackson 的 Streaming API,但所需的代码难以理解和维护。相反,如果可能,我想使用Jerkson返回一个表示已解析 JSON 的对象。

基本上:我想在动态语言中复制我非常熟悉的 JSON 解析功能。我意识到这可能是非常错误的,所以我来这里接受教育。

假设我们有一条推文:

{
 "id": 100,
 "text": "Hello, world."
 "user": {
          "name": "Brett",
          "id": 200
         },
 "geo": {
         "lat": 10.5,
         "lng": 20.7 
        }
}

现在,当您只想解析出 ID 时,Jerkson Case Class 示例很有意义:

val tweet = """{...}"""
case class Tweet(id: Long)
val parsed = parse[Tweet](tweet)

但是我该如何处理上面的推文呢?

一些陷阱:

  1. 某些字段可能是null或缺失,例如上面的“geo”可能是null,或者有一天他们可能会删除一个字段,我不希望我的解析代码失败。
  2. 某些字段将是额外的,或者将添加字段并且我希望能够忽略它们。
4

3 回答 3

3

Lift json-scalaz 是我遇到的最好的 JSON 读写方式。文档在这里很好地解释了它的用法:

https://github.com/lift/framework/tree/master/core/json-scalaz

于 2012-07-19T22:45:51.423 回答
1

当然,在我发布这个之后,我在其他地方找到了一些帮助。:)

我相信这篇文章底部的“更丰富的 JSON 示例”是朝着正确方向迈出的一步:http: //bcomposes.wordpress.com/2012/05/12/processing-json-in-scala-with-jerkson/

于 2012-07-19T20:20:27.580 回答
1

另一个使用 Lift-json 的替代方法可能是:

package code.json

import org.specs2.mutable.Specification
import net.liftweb.json._

class JsonSpecs extends Specification {

  implicit val format = DefaultFormats

  val a = parse("""{
                  | "id": 100,
                  | "text": "Hello, world."
                  | "user": {
                  |          "name": "Brett",
                  |          "id": 200
                  |         },
                  | "geo": {
                  |         "lat": 10.5,
                  |         "lng": 20.7
                  |        }
                  |}""".stripMargin)

  val b = parse("""{
                  | "id": 100,
                  | "text": "Hello, world."
                  | "user": {
                  |          "name": "Brett",
                  |          "id": 200
                  |         }
                  |}""".stripMargin)


  "Lift Json" should{
    "find the id" in {
      val res= (a \ "id").extract[String]
      res must_== "100"
    }
    "find the name" in{
      val res= (a \ "user" \ "name").extract[String]
      res must_== "Brett"
    }
    "find an optional geo data" in {
      val res= (a \ "geo" \ "lat").extract[Option[Double]]
      res must_== Some(10.5)
    }
    "ignore missing geo data" in {
      val res= (b \ "geo" \ "lat").extract[Option[Double]]
      res must_== None
    }
  }
}

请注意,当 val b 上缺少地理数据时,解析工作得很好,期待无。

或者你想得到案例类作为结果?

有关案例类示例,请参见:

包代码.json

import org.specs2.mutable.Specification
import net.liftweb.json._

class JsonSpecs extends Specification {

  implicit val format = DefaultFormats

  case class Root(id: Int, text: Option[String], user: Option[User], geo: Option[Geo])
  case class User(name: String, id: Int)
  case class Geo(lat: Double, lng: Double)



val c = parse("""{
                | "id": 100
                | "user": {
                |          "name": "Brett",
                |          "id": 200
                |         },
                | "geo": {
                |         "lng": 20.7
                |        }
                |}""".stripMargin)


  "Lift Json" should{
    "return none for geo lat data" in {
      val res= c.extract[Root].geo.map(_.lat)
      res must_== None
    }
  }
}
于 2012-07-21T19:54:24.517 回答