web-dev-qa-db-ja.com

Scala / LiftでJSON文字列を構築および解析するにはどうすればよいですか?

JSONを使用して、ブラウザーとアプリ間でデータを送信しようとしています。

Lift 1.0を使用してJSON文字列を作成および解析しようとしていますが、何らかの理由で、作成したJSONを解析できません。

scala>import scala.util.parsing.json.JSON._
import scala.util.parsing.json.JSON._

scala> import net.liftweb.http.js._
import net.liftweb.http.js._

scala> import net.liftweb.http.js.JE._
import net.liftweb.http.js.JE._

scala> val json = JsObj(("foo", 4), ("bar", "baz")).toJsCmd
json: String = {'foo': 4, 'bar': 'baz'}

scala>  parseFull(json)  
res3: Option[Any] = None

Scala/Liftで有効なJSONメッセージをプログラムで作成し、再度解析する方法を教えてください。

55
David Carlson

Lift 1.0のJsCmdを使用しています。これは、単一引用符で囲まれた文字列でJSONを生成し、二重引用符で囲まれた文字列のみをサポートするscalaのパーサーで解析しようとしています。

JSONには複数の定義があることを認識することが重要です。

JSONで一重引用符で囲まれた文字列は有効ですか?

LiftとScalaはJSONを解析する多くの方法を提供し、バージョン間で動作が異なる場合があります。

これらのパーサーが受け入れる文字列は同等ではありません。

JSON文字列を生成および解析するためのさまざまなメソッドのコメントと例は次のとおりです。


lift-json ライブラリDSLでJSONを生成する

  • お勧め
  • 名前にもかかわらず、これはLiftの残りの部分に依存しない独立したプロジェクトです

例:

scala> import net.liftweb.json.JsonAST
import net.liftweb.json.JsonAST

scala> import net.liftweb.json.JsonDSL._
import net.liftweb.json.JsonDSL._

scala> import net.liftweb.json.Printer._
import net.liftweb.json.Printer._

scala> val json1 = ("foo" -> 4) ~ ("bar" -> "baz")
json1: net.liftweb.json.JsonAST.JObject = JObject(List(JField(foo,JInt(4)), JField(bar,JString(baz))))

scala> compact(JsonAST.render(json1))
res0: String = {"foo":4,"bar":"baz"}

scala> val json2 = List(1,2,3)
json2: List[Int] = List(1, 2, 3)

scala> compact(JsonAST.render(json2))
res1: String = [1,2,3]

scala> val json3 = ("foo", 4) ~ ("bar", List(1,2,3))
json3: net.liftweb.json.JsonAST.JObject = JObject(List(JField(foo,JInt(4)), JField(bar,JArray(List(JInt(1), JInt(2), JInt(3))))))

scala> compact(JsonAST.render(json3))
res2: String = {"foo":4,"bar":[1,2,3]}

lift-json ライブラリを使用したJSONの解析

  • お勧め
  • scala case-classesとの間の暗黙的なマッピングを提供します
  • コンソールで定義されたケースクラスは現在サポートされていません(com.thoughtworks.paranamer.ParameterNamesNotFoundException: Unable to get class bytesをスローします)
  • 以下の例では、既存のscala case-classであるPublicIDを使用して、scalaコンソールで動作します。

例:

scala> import scala.xml.dtd.PublicID
import scala.xml.dtd.PublicID

scala> import net.liftweb.json._
import net.liftweb.json._

scala> import net.liftweb.json.JsonAST._
import net.liftweb.json.JsonAST._

scala> import net.liftweb.json.JsonDSL._
import net.liftweb.json.JsonDSL._

scala> implicit val formats = DefaultFormats 
formats: net.liftweb.json.DefaultFormats.type = net.liftweb.json.DefaultFormats$@7fa27edd

scala> val jsonAst = ("publicId1" -> "idString") ~ ("systemId" -> "systemIdStr")
jsonAst: net.liftweb.json.JsonAST.JObject = JObject(List(JField(publicId,JString(idString)), JField(systemId,JString(systemIdStr))))

scala> jsonAst.extract[PublicID]
res0: scala.xml.dtd.PublicID = PUBLIC "idString" "systemIdStr"

scala 2.7.7および2.8.1でのJSONの解析

例:

scala>import scala.util.parsing.json.JSON._
import scala.util.parsing.json.JSON._

scala>  parseFull("{\"foo\" : 4 }")        
res1: Option[Any] = Some(Map(foo -> 4.0))

scala> parseFull("[ 1,2,3 ]")
res2: Option[Any] = Some(List(1.0, 2.0, 3.0))

scala>  parseFull("{'foo' : 4 }")  
res3: Option[Any] = None

til.JSONParser を使用したLift 2.0および2.2でのJSONの解析

  • ニュートラルレコメンデーション
  • Liftのutil.JSONParserは、一重引用符または二重引用符で囲まれたJSON文字列を解析します。

例:

scala> import net.liftweb.util.JSONParser._
import net.liftweb.util.JSONParser._

scala> parse("{\"foo\" : 4 }")    
res1: net.liftweb.common.Box[Any] = Full(Map(foo -> 4.0))

scala> parse("[ 1,2,3 ]")
res2: net.liftweb.common.Box[Any] = Full(List(1.0, 2.0, 3.0))

scala> parse("{'foo' : 4}")           
res3: net.liftweb.common.Box[Any] = Full(Map(foo -> 4.0))

json.JsonParser を使用したLift 2.0および2.2でのJSONの解析

  • ニュートラルレコメンデーション
  • Liftのjson.JsonParserは、単一引用符で囲まれたJSON文字列を解析しません。

例:

scala> import net.liftweb.json._
import net.liftweb.json._

scala> import net.liftweb.json.JsonParser._
import net.liftweb.json.JsonParser._

scala> parse("{\"foo\" : 4 }")
res1: net.liftweb.json.JsonAST.JValue = JObject(List(JField(foo,JInt(4))))

scala> parse("[ 1,2,3 ]")
res2: net.liftweb.json.JsonAST.JValue = JArray(List(JInt(1), JInt(2), JInt(3)))

scala> parse("{'foo' : 4}")    
net.liftweb.json.JsonParser$ParseException: unknown token '
Near: {'foo' : 4}
    at net.liftweb.json.JsonParser$Parser.fail(JsonParser.scala:216)
    at net.liftweb.json.JsonParser$Parser.nextToken(JsonParser.scala:308)
    at net.liftweb.json.JsonParser$$anonfun$1.apply(JsonParser.scala:172)
    at net.liftweb.json.JsonParser$$anonfun$1.apply(JsonParser.scala:129)
    at net.liftweb.json.JsonParse...

Lift 1.0 JsCmdを使用したJSONの作成

  • 非推奨-すべてのJSONパーサーに対して出力が有効ではない
  • 文字列を囲む一重引用符に注意してください。

例:

scala> import net.liftweb.http.js._
import net.liftweb.http.js._

scala> import net.liftweb.http.js.JE._
import net.liftweb.http.js.JE._

scala> JsObj(("foo", 4), ("bar", "baz")).toJsCmd
res0: String = {'foo': 4, 'bar': 'baz'}

scala> JsArray(1,2,3).toJsCmd
res1: String = 
[1, 2, 3]

scala>  JsObj(("foo", 4), ("bar", JsArray(1,2,3))).toJsCmd
res2: String = 
{'foo': 4, 'bar': [1, 2, 3]
}

Lift 2.0 JsCmdでJSONを生成する

  • ニュートラルレコメンデーション
  • 文字列を囲む二重引用符に注意してください。

例:

scala> import net.liftweb.http.js._
import net.liftweb.http.js._

scala> import net.liftweb.http.js.JE._
import net.liftweb.http.js.JE._

scala> JsObj(("foo", 4), ("bar", "baz")).toJsCmd
res0: String = {"foo": 4, "bar": "baz"}

scala> JsArray(1,2,3).toJsCmd
res1: String = 
[1, 2, 3]

scala> JsObj(("foo", 4), ("bar", JsArray(1,2,3))).toJsCmd
res3: String = 
{"foo": 4, "bar": [1, 2, 3]
}

scalaでJSONを生成(2.10でテスト済み)

例:

scala> import scala.util.parsing.json._
import scala.util.parsing.json._

scala> JSONObject (Map ("foo" -> 4, "bar" -> JSONArray (1 :: 2 :: 3 :: Nil))) .toString()
res0: String = {"foo" : 4, "bar" : [1, 2, 3]}
88
David Carlson

Circe を見てください。本当に使いやすく、 Shapeless および Cats の新しいツールを活用しています。さらに、 Javascriptにコンパイルされたスカラ から使用できます。

Circe readme から取得:

scala> import io.circe。、io.circe.generic.auto。、io.circe.parser。 、io.circe.syntax。import io.circe._ import io.circe.generic.auto._ import io.circe.parser._ import io.circe.syntax._

scala>封印された特性Foo定義された特性Foo

scala> case class Bar(xs:List [String])はFoo定義クラスBarを拡張します

scala> case class Qux(i:Int、d:Option [Double])はFoo定義クラスQuxを拡張します

scala> val foo:Foo = Qux(13、Some(14.0))foo:Foo = Qux(13、Some(14.0))

scala> foo.asJson.noSpaces res0:文字列= {"Qux":{"d":14.0、 "i":13}}

scala> decodeFoo res1:cats.data.Xor [io.circe.Error、Foo] = Right(Qux(13、Some(14.0)))

0
James Moore