3

他の Scala JSON 解析の質問を読んだことがありますが、それらはすべて、深くネストされていない、または型が混在していない非常に基本的なドキュメントを想定しているようです。または、ドキュメントのすべてのメンバーを知っているか、一部が失われることはないと想定しています。

現在、Jackson のストリーミング API を使用していますが、必要なコードの理解と保守が困難です。代わりに、Jerksonを使用して、可能であれば解析された JSON を表すオブジェクトを返したいと思います。

基本的には、動的言語でよく知っている JSON 解析機能を複製したいと考えています。私はそれがおそらく非常に間違っていることを理解しているので、私は教育を受けるためにここにいます.

ツイートがあるとします:

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

さて、Jerkson Case Class の例は、たとえば ID のみを解析したい場合に非常に役立ちます。

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

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 で欠落している場合、None を想定して解析が正常に機能することに注意してください。

または、結果としてケース クラスを取得しますか?

ケース クラスの例については、次を参照してください。

パッケージ code.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 に答える
1

もちろん、これを投稿した直後に、他の場所で助けを見つけました。:)

この投稿の下部にある「よりリッチな JSON の例」は正しい方向への一歩だと思います: http://bcomposes.wordpress.com/2012/05/12/processing-json-in-scala-with-jerkson/

于 2012-07-19T20:20:27.580 に答える