将JSON映射到Scala对象的最有效方法是什么?

时间:2016-03-08 22:38:39

标签: json scala playframework playframework-2.0

我想用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”// logic:urn.split(“:”)(1)+“_”+ key

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

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

目前我将创建一个中间案例类,它只是从JSON中提取相关属性(id,urn,key),并在下一步中将这些对象映射到自定义的所需结构。我不知何故觉得这不是可行的方法。

2 个答案:

答案 0 :(得分:2)

您可以在自定义读取/写入序列化程序中添加此类逻辑。请参阅我的答案,了解如何添加自定义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))
  }
}

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

答案 1 :(得分:1)

您需要使用Json transformer

 "Fatal error: Class 'Expression' not found in 
C:\Users\nobis\code\testing2\tests\ExpressionTest.php on line 8"

您的转换结果示例:

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

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