サーチ…


JSON with spray-json

spray-jsonはJSONで簡単に作業できます。暗黙的なフォーマットを使用すると、すべてが「舞台裏で」起こります。

SBTでライブラリを利用できるようにする

SBTが管理するライブラリの依存関係を持つspray-json管理するには

libraryDependencies += "io.spray" %% "spray-json" % "1.3.2"

最後のパラメータであるバージョン番号( 1.3.2 )は、プロジェクトによって異なる場合があります。

spray-jsonライブラリはrepo.spray.ioでホストされています

ライブラリをインポートする

import spray.json._
import DefaultJsonProtocol._

デフォルトのJSONプロトコルDefaultJsonProtocolは、すべての基本タイプのフォーマットが含まれています。カスタム・タイプにJSON機能を提供するには、フォーマットに便利なBuilderを使用するか、明示的に書式を書いてください。

JSONを読む

// generates an intermediate JSON representation (abstract syntax tree)
val res = """{ "foo": "bar" }""".parseJson // JsValue = {"foo":"bar"}

res.convertTo[Map[String, String]] // Map(foo -> bar)

JSONを書く

val values = List("a", "b", "c")
values.toJson.prettyPrint // ["a", "b", "c"]

DSL

DSLはサポートされていません。

ケースクラスへの読み書き

次の例は、ケース・クラス・オブジェクトをJSON形式にシリアル化する方法を示しています。

case class Address(street: String, city: String)
case class Person(name: String, address: Address)

// create the formats and provide them implicitly
implicit val addressFormat = jsonFormat2(Address)
implicit val personFormat = jsonFormat2(Person)

// serialize a Person
Person("Fred", Address("Awesome Street 9", "SuperCity"))
val fredJsonString = fred.toJson.prettyPrint

これにより、次のJSONが生成されます。

{
  "name": "Fred",
  "address": {
    "street": "Awesome Street 9",
    "city": "SuperCity"
  }
}

次に、JSONを逆シリアル化してオブジェクトに戻すことができます。

val personRead = fredJsonString.parseJson.convertTo[Person] 
//Person(Fred,Address(Awesome Street 9,SuperCity))

カスタムフォーマット

型の特殊な直列化が必要な場合は、 カスタムJsonFormatます。たとえば、Scalaでフィールド名がJSONと異なる場合。あるいは、異なるコンクリート型が入力に基づいてインスタンス化されている場合。

implicit object BetterPersonFormat extends JsonFormat[Person] {
    // deserialization code
    override def read(json: JsValue): Person = {
        val fields = json.asJsObject("Person object expected").fields
        Person(
            name = fields("name").convertTo[String],
            address = fields("home").convertTo[Address]
        )
    }

    // serialization code
    override def write(person: Person): JsValue = JsObject(
        "name" -> person.name.toJson,
        "home" -> person.address.toJson
    )
}

JSON with Circe

Circeは、en / decode jsonのコンパイル時に派生したコーデックをケースクラスに提供します。簡単な例は次のようになります。

import io.circe._
import io.circe.generic.auto._
import io.circe.parser._
import io.circe.syntax._

case class User(id: Long, name: String)

val user = User(1, "John Doe")

// {"id":1,"name":"John Doe"}
val json = user.asJson.noSpaces

// Right(User(1L, "John Doe"))
val res: Either[Error, User] = decode[User](json)

JSON with play-json

play-jsonは暗黙の形式を他のjsonフレームワークとして使用します

SBT依存性: libraryDependencies += ""com.typesafe.play" %% "play-json" % "2.4.8"

import play.api.libs.json._
import play.api.libs.functional.syntax._ // if you need DSL

DefaultFormatは、すべての基本型を読み書きするためのデフォルト形式が含まれています。独自の型に対してJSON機能を提供するには、フォーマットに便利なBuilderを使用するか、明示的に書式を書いてください。

jsonを読む

// generates an intermediate JSON representation (abstract syntax tree)
val res = Json.parse("""{ "foo": "bar" }""") // JsValue = {"foo":"bar"}

res.as[Map[String, String]]                  // Map(foo -> bar)
res.validate[Map[String, String]]            //JsSuccess(Map(foo -> bar),)

jsonを書く

val values = List("a", "b", "c")
Json.stringify(Json.toJson(values))          // ["a", "b", "c"]

DSL

val json = parse("""{ "foo": [{"foo": "bar"}]}""")
(json \ "foo").get                    //Simple path: [{"foo":"bar"}]
(json \\ "foo")                       //Recursive path:List([{"foo":"bar"}], "bar")
(json \ "foo")(0).get                  //Index lookup (for JsArrays): {"foo":"bar"}

常にJsSuccess / JsErrorに対するパターンマッチングをJsSuccessし、 .getarray(i)呼び出しを避けようとします。

ケースクラスの読み書き

case class Address(street: String, city: String)
case class Person(name: String, address: Address)

// create the formats and provide them implicitly
implicit val addressFormat = Json.format[Address]
implicit val personFormat = Json.format[Person]

// serialize a Person
val fred = Person("Fred", Address("Awesome Street 9", "SuperCity"))
val fredJsonString = Json.stringify(Json.toJson(Json.toJson(fred)))

val personRead = Json.parse(fredJsonString).as[Person] //Person(Fred,Address(Awesome Street 9,SuperCity))

自分のフォーマット

型の特殊なシリアル化が必要な場合は、独自のJsonFormatを記述することができます(たとえば、scalaやJsonではフィールドの名前を異なるようにするか、入力に基づいて異なる具体的な型をインスタンス化します)

case class Address(street: String, city: String)

// create the formats and provide them implicitly
implicit object AddressFormatCustom extends Format[Address] {
  def reads(json: JsValue): JsResult[Address] = for {
    street <- (json \ "Street").validate[String]
    city <- (json \ "City").validate[String]
  } yield Address(street, city)

  def writes(x: Address): JsValue = Json.obj(
    "Street" -> x.street,
    "City" -> x.city
  )
}
// serialize an address
val address = Address("Awesome Street 9", "SuperCity")
val addressJsonString = Json.stringify(Json.toJson(Json.toJson(address)))
//{"Street":"Awesome Street 9","City":"SuperCity"}

val addressRead = Json.parse(addressJsonString).as[Address] 
//Address(Awesome Street 9,SuperCity)

オルタナティブ

JSONは正確に(あなたのケースクラスのフィールドと一致しない場合isAlive対ケースクラスにis_alive JSONで):

case class User(username: String, friends: Int, enemies: Int, isAlive: Boolean)

object User {

  import play.api.libs.functional.syntax._
  import play.api.libs.json._

  implicit val userReads: Reads[User] = (
      (JsPath \ "username").read[String] and
      (JsPath \ "friends").read[Int] and
      (JsPath \ "enemies").read[Int] and
      (JsPath \ "is_alive").read[Boolean]
    ) (User.apply _)
}

オプションフィールドを持つJson

case class User(username: String, friends: Int, enemies: Int, isAlive: Option[Boolean])

object User {

  import play.api.libs.functional.syntax._
  import play.api.libs.json._

  implicit val userReads: Reads[User] = (
      (JsPath \ "username").read[String] and
      (JsPath \ "friends").read[Int] and
      (JsPath \ "enemies").read[Int] and
      (JsPath \ "is_alive").readNullable[Boolean]
    ) (User.apply _)
}

jsonのタイムスタンプを読む

Unixタイムスタンプフィールドを持つJsonオブジェクトがあるとします。

{
  "field": "example field",
  "date": 1459014762000
}

溶液:

case class JsonExampleV1(field: String, date: DateTime)
object JsonExampleV1{
  implicit val r: Reads[JsonExampleV1] = (
    (__ \ "field").read[String] and
      (__ \ "date").read[DateTime](Reads.DefaultJodaDateReads)
    )(JsonExampleV1.apply _)
}

カスタムケースクラスの読み込み

今、型の安全性のためにオブジェクト識別子をラップすると、これを楽しむことができます。次のjsonオブジェクトを参照してください。

{
  "id": 91,
  "data": "Some data"
}

対応するケースクラス:

case class MyIdentifier(id: Long)

case class JsonExampleV2(id: MyIdentifier, data: String)

これで、プリミティブ型(Long)を読み、あなたのidenfierにマップするだけです:

object JsonExampleV2 {
  implicit val r: Reads[JsonExampleV2] = (
      (__ \ "id").read[Long].map(MyIdentifier) and
    (__ \ "data").read[String]
    )(JsonExampleV2.apply _)
}

コード:https://github.com/pedrorijo91/scala-play-json-examples

JSONとjson4s

json4sは暗黙の形式を他のjsonフレームワークとして使用します。

SBTの依存関係:

libraryDependencies += "org.json4s" %% "json4s-native" % "3.4.0"
//or
libraryDependencies += "org.json4s" %% "json4s-jackson" % "3.4.0"

輸入

import org.json4s.JsonDSL._
import org.json4s._
import org.json4s.native.JsonMethods._

implicit val formats = DefaultFormats

DefaultFormatsは、すべての基本型を読み書きするための既定の形式が含まれています。

jsonを読む

// generates an intermediate JSON representation (abstract syntax tree)
val res = parse("""{ "foo": "bar" }""")           // JValue = {"foo":"bar"}
res.extract[Map[String, String]]                  // Map(foo -> bar)

jsonを書く

val values = List("a", "b", "c")
compact(render(values))         // ["a", "b", "c"]

DSL

json \ "foo"       //Simple path: JArray(List(JObject(List((foo,JString(bar))))))
json \\ "foo"      //Recursive path: ~List([{"foo":"bar"}], "bar")
(json \ "foo")(0)  //Index lookup (for JsArrays): JObject(List((foo,JString(bar))))
("foo" -> "bar") ~ ("field" -> "value")    // {"foo":"bar","field":"value"}

ケースクラスの読み書き

import org.json4s.native.Serialization.{read, write}

case class Address(street: String, city: String)
val addressString = write(Address("Awesome stree", "Super city")) 
// {"street":"Awesome stree","city":"Super city"}

read[Address](addressString) // Address(Awesome stree,Super city)
//or
parse(addressString).extract[Address]

異種リストの読み取りと書き込み

異種(または多相)のリストを直列化および逆直列化するには、特定の型ヒントを提供する必要があります。

trait Location
case class Street(name: String) extends Location
case class City(name: String, zipcode: String) extends Location
case class Address(street: Street, city: City) extends Location
case class Locations (locations : List[Location])

implicit val formats = Serialization.formats(ShortTypeHints(List(classOf[Street], classOf[City], classOf[Address])))

val locationsString = write(Locations(Street("Lavelle Street"):: City("Super city","74658")))

read[Locations](locationsString)

自分のフォーマット

class AddressSerializer extends CustomSerializer[Address](format => (
  {
    case JObject(JField("Street", JString(s)) :: JField("City", JString(c)) :: Nil) =>
      new Address(s, c)
  },
  {
    case x: Address => ("Street" -> x.street) ~ ("City" -> x.city)
  }
  ))

implicit val formats = DefaultFormats + new AddressSerializer
val str = write[Address](Address("Awesome Stree", "Super City"))
// {"Street":"Awesome Stree","City":"Super City"}
read[Address](str) 
// Address(Awesome Stree,Super City)


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow