首页 > 解决方案 > Scala Play:列表到 Json-Array

问题描述

我有一个包含一些个性化对象的列表。后者定义如下:

  sealed case class Personalization(firstname: String, lastname: String, keycardId: String)

我需要将此列表映射到一个 Json-Array 结构,该结构必须如下所示:

"personalization": [
    {
      "id": "firstname",
      "value": "John"
    },
    {
      "id": "lastname",
      "value": "Doe"
    }...

我正在努力将字段信息映射到 id/value 对。通常,我会从 Personalization 类中创建一个 play.api.libs.json.Format 并让它自动映射 -> Json.format[Personalization]- 但是这一次,我需要创建一个数组,其中一个条目可以包含 n 个属性。

因此,我征求意见,是否有可能使用 Scala Play-Framework?非常感谢任何输入,谢谢!

标签: jsonscalaplay-json

解决方案


编写这样的 JSON 表示并不是很复杂,使用Writes.transform.

import play.api.libs.json._

case class Personalization(firstname: String, lastname: String, keycardId: String) // No need to seal a case class

implicit def writes: Writes[Personalization] = {
  val tx: JsValue => JsValue = {
    case JsObject(fields) => Json.toJson(fields.map {
      case (k, v) => Json.obj("id" -> k, "value" -> v)
    })

    case jsUnexpected => jsUnexpected // doesn't happen with OWrites
  }

  Json.writes[Personalization].transform(tx)
}

可以如下测试。

val personalization = Personalization(
  firstname = "First",
  lastname = "Last",
  keycardId = "Foo")

val jsonRepr = Json.toJson(personalization)
// => [{"id":"firstname","value":"First"},{"id":"lastname","value":"Last"},{"id":"keycardId","value":"Foo"}]

阅读有点棘手:

implicit def reads: Reads[Personalization] = {
  type Field = (String, Json.JsValueWrapper)

  val fieldReads = Reads.seq(Reads[Field] { js =>
    for {
      id <- (js \ "id").validate[String]
      v <- (js \ "value").validate[JsValue]
    } yield id -> v
  })

  val underlying = Json.reads[Personalization]

  Reads[Personalization] { js =>
    js.validate(fieldReads).flatMap { fields =>
      Json.obj(fields: _*).validate(underlying)
    }
  }
}

可以如下测试。

Json.parse("""[
  {"id":"firstname","value":"First"},
  {"id":"lastname","value":"Last"},
  {"id":"keycardId","value":"Foo"}
]""").validate[Personalization]
// => JsSuccess(Personalization(First,Last,Foo),)

请注意,这种方法可用于任何案例类格式。


推荐阅读