【问题标题】:What is the most efficient way to map JSON to Scala Objects?将 JSON 映射到 Scala 对象的最有效方法是什么?
【发布时间】:2016-03-08 22:38:38
【问题描述】:

我想用 Play 库解析一些“复杂”的 JSON。

import play.api.libs.json._

假设我从服务器获得了一个包含许多 JSON 对象的数组,我无法修改该数组。每个条目看起来都类似于这个:

{
  "id": 1,
  "urn": "urn:article:5",
  "key": "post",
  "foo": "useless"
}

最后我想将此结构映射到具有以下值的 Scala 对象:

  • id: Int = 1
  • urn: String = "urn:user:5"
  • type: String = "article_post" // 逻辑:urn.split(":")(1) + "_" + key

什么是最有效的方法?将 JSON 框架内的结构映射到我的需要,还是应该尽快使用中间案例类将它们映射到我的自定义结构中?

我查看了official documentation,但他们似乎没有讨论这个问题。

目前我将创建一个中间案例类,它只是从 JSON 中提取相关属性(id、urn、key),并在后续步骤中将这些对象映射到我想要的自定义结构。我不知何故觉得这不是要走的路。

【问题讨论】:

  • 据我了解,您需要Json transformers 进行验证。使用变压器,您不需要持有人课程。

标签: json scala playframework playframework-2.0


【解决方案1】:

您可以在自定义读/写序列化程序中添加这种逻辑。请参阅我关于如何添加自定义 JSON Writer for Seq of Tuple 的答案。在这种情况下,我会创建一个Writes,在您的情况下,您将创建一个Reads,因为您正在读取 JSON 并转换为一个类的实例,很可能是一个案例类。

例如

case class Wombat(id: Int, urn: String, `type`: String)
implicit val myWombatReads = new Reads[Wombat] {
  def reads(js: JsValue): JsResult[Wombat] = {
    val id = (js \ "id").as[Int]
    val urn = (js \ "urn").as[String]
    val key = (js \ "key").as[String]
    JsSuccess(Wombat(id, urn, urn.split(":")(1) + "_" + key))
  }
}

我没有测试你的自定义逻辑,但你明白了。您还可以添加验证器等。

【讨论】:

  • 小心as[XXXX] 抛出异常。
  • 是的,如果你不控制客户端,我为什么建议验证器。
【解决方案2】:

你需要使用Json transformer

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

val t =  (

  (__ \ "id").json.copyFrom( (__ \ "id").json.pick) and
    (__ \ "urn").json.copyFrom( (__ \ "urn").json.pick) and
    ( __ \ "type").json.copyFrom(
      (__ \ "urn").read[String].flatMap(urn =>
        (__ \ "key").read[String].map(key =>
          JsString(urn.split(":")(1) + "_" + key)
        )
      )
    )
  ).reduce

你的转换结果示例:

json.transform(t)

scala> json: play.api.libs.json.JsValue = {"id":1,"urn":"urn:article:5","key":"post","foo":"useless"}

scala> res2: play.api.libs.json.JsResult[play.api.libs.json.JsObject] = JsSuccess({"id":1,"urn":"urn:article:5","type":"article_post"},)

您还可以添加一些验证。 coast-to-coast desig 的好文章。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-24
    • 1970-01-01
    • 1970-01-01
    • 2019-05-27
    相关资源
    最近更新 更多