帶有 play-json 的 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 功能,你可以使用便捷構建器來顯示格式或寫入格式。

讀 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 並儘量避免 .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 與你的 case 類欄位不完全匹配(案例類中的 isAlive 和 json 中的 is_alive):

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