Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala播放:列表到Json数组_Json_Scala_Play Json - Fatal编程技术网

Scala播放:列表到Json数组

Scala播放:列表到Json数组,json,scala,play-json,Json,Scala,Play Json,我有一个包含一些个性化对象的列表。后者的定义如下: sealed case class Personalization(firstname: String, lastname: String, keycardId: String) "personalization": [ { "id": "firstname", "value": "John" },

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

  sealed case class Personalization(firstname: String, lastname: String, keycardId: String)
"personalization": [
    {
      "id": "firstname",
      "value": "John"
    },
    {
      "id": "lastname",
      "value": "Doe"
    }...
我需要将此列表映射到Json数组结构,该结构必须如下所示:

  sealed case class Personalization(firstname: String, lastname: String, keycardId: String)
"personalization": [
    {
      "id": "firstname",
      "value": "John"
    },
    {
      "id": "lastname",
      "value": "Doe"
    }...
我正在努力将字段信息映射到id/值对。通常,我会在Personalization类中创建play.api.libs.json.Format,并让它自动映射->
json.Format[Personalization]
——但这次,我需要创建一个数组,其中一个条目可以容纳n个属性

因此,我在征求意见,是否有可能使用Scala Play框架?
非常感谢您的任何意见,谢谢

也许我可以用更优雅的方式来做,但您可以使用以下代码片段:

case class Field(id: String, value: String)

object Field {
  implicit val fieldFormatter: Format[Field] = Json.format[Field]
}

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

object Personalization {

  implicit val personalizationFormatter: Format[Personalization] = new Format[Personalization] {
    override def reads(json:  JsValue): JsResult[Personalization] =
      Try {
        val data = (json \ "personalization").as[JsValue]
        data match {
          case JsArray(value) =>
            val fields = value.map(_.as[Field]).map(f => f.id -> f.value).toMap
            val firstname = fields.getOrElse("firstname", throw new IllegalArgumentException("Mandatory field firstname is absent."))
            val lastname = fields.getOrElse("lastname", throw new IllegalArgumentException("Mandatory field lastname is absent."))
            val keycardId = fields.getOrElse("keycardId", throw new IllegalArgumentException("Mandatory field keycardId is absent."))
            Personalization(firstname, lastname, keycardId)
          case _ => throw new IllegalArgumentException("Incorrect json format for Personalization.")
        }
      }.toEither.fold(e => JsError(e.getMessage), JsSuccess(_))

    override def writes(o:  Personalization): JsValue = {
      val fields = List(Field("firstname", o.firstname), Field("lastname", o.lastname), Field("keycardId", o.keycardId))
      JsObject(List("personalization" -> Json.toJson(fields)))
    }
  }
}

它将
{“personalization”:[{“id”:“firstname”,“value”:“John”},{“id”:“lastname”,“value”:“Doe”},{“id”:“keycardId”,“value”:“1234”}]}
转换为
个性化(John,Doe,1234)
,反之亦然

使用
编写JSON表示并不十分复杂

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"}]
Json.parse("""[
  {"id":"firstname","value":"First"},
  {"id":"lastname","value":"Last"},
  {"id":"keycardId","value":"Foo"}
]""").validate[Personalization]
// => JsSuccess(Personalization(First,Last,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)
    }
  }
}
注意,is方法可用于任何案例类格式


即使在
Try
中也不建议引发异常,特别是当可以使用
JsResult
时。
最好使用
。as