2016-03-08 71 views
0

我想用Play库解析一些“复杂”的JSON。什么是将JSON映射到Scala对象的最有效方法?

import play.api.libs.json._ 

我们假设我从一个服务器中得到一个包含许多JSON对象的数组,我无法修改。每个条目类似于此之一:

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

最后,我想该结构映射到一个Scala的对象具有以下值:

  • ID:INT = 1
  • 瓮:字符串= “瓮:用户:5”
  • 类型:字符串= “article_post” //逻辑:urn.split( “:”)(1)+ “_” +键

什么是最高效的方式?将JSON框架内的结构映射到我的需求,还是应尽快使用中间案例类将这些结构映射到我的自定义结构中?

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

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

+0

据我所知,你需要[Json变形金刚](https://www.playframework.com/documentation/2.4.x/ScalaJsonTransformers)验证。变压器你不需要持有人类。 –

回答

2

您可以在自定义的Reads/Writes序列化程序中添加这种逻辑。看到我的答案如何添加自定义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)) 
    } 
} 

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

+0

注意'因为[XXXX]'抛出异常。 –

+0

是的,如果你不控制客户端的话,我为什么建议验证器。 – andyczerwonka

1

您需要使用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 

transfomation结果为您例如:

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