播放 Json - 复杂对象创建



我正在尝试在我的Play框架应用程序(Scala)中创建Json阅读器。问题是,我的 Json 的一部分有点时髦,需要进一步处理才能检索值。例如:

{  
  "field1":"value1",
  "field2":"value/1",
  "num2":2
}

使用案例类:

case class Field1(text: String, fields: Field2)
case class Field2(text: String, num: Int, num2: Int)

基本上Field2textnum字段都是通过拆分文本从值value/1派生出来的。这是拆分器函数:

def splitter(path: String, num2: Int): Field2 = {
  val split = path.split("\")
  Field2(split(0), split(1).toInt, num2)
}

这是相当简单的,实际的拆分器功能要复杂得多。基本上,构造此对象Field2的唯一方法是将单个字符串传递给吐出所需对象的函数。

如何为Field2创建阅读器(以及扩展Field1)?

这是我到目前为止所拥有的:

object Field1 {
    implicit val reader = (
        (__  "field1").read[String] and
        (__).read[Field2]
    ) (Field1.apply _)
}
object Field2 {
    implicit val reader = (
        splitter((__  "field2").read[String], (__  "num2"))
    ) // Obviously incorrect syntax + type mismatch, but this is roughly what I'm trying to accomplish.
}

如果你使用非函数组合器语法,我认为它会变得简单一些:

object Field2 {
  implicit val reader = Reads[Field2] { json =>
    for {
      path <- (json  "field2").validate[String]
      num2 <- (json  "num2").validate[Int]
    } yield splitter(path, num2)
  }
}

此外,如果您希望拆分器进一步验证输入,请使其返回如下JsResult[Field2]

def splitter(path: String, num2: Int): JsResult[Field2] = {
  val split = path.split("\")
  if (split.size != 2) {
    JsError(s"$path must be of the form: {field}\{num}")
  } else {
    Try(Field2(split(0), split(1).toInt, num2)).map(JsSuccess(_)).getOrElse {
      JsError(s"${split(1)} is not a valid Int")
    }
  }
}

然后修改阅读器:

object Field2 {
  implicit val reader = Reads[Field2] { json =>
    for {
      path <- (json  "field2").validate[String]
      num2 <- (json  "num2").validate[Int]
      field2 <- splitter(path, num2)
    } yield field2
  }
}

如果您仍然喜欢使用函数语法,并且您不介意缺乏验证,拆分器确实可以尝试以下方法:

def splitter(path: String, num2: Int): Field2 = {
  val split = path.split("\")
  Field2(split(0), split(1).toInt, num2)
}
implicit val reader = (
  (__  "field2").read[String] and
  (__  "num2").read[Int]
)(splitter _)

我建议不要这样做,这是不安全的(split(1)toInt两者都可能引发异常),并且功能语法可能存在性能问题。请参阅 https://www.lucidchart.com/techblog/2016/08/29/speeding-up-restful-services-in-play-framework/。

我不知道

为什么需要案例类,但您也可以根据需要转换 json

 (__  "field2"  "num2").json.copyFrom((__  "num2").json.pick) and
    (__  "field2").json.update(
      of[String].map { o =>
        val split = o.split("/")
        Json.obj(
          "text" -> split(0),
          "num" -> split(1).toInt
        )
      }
    )
  ).reduce andThen (__  "num2").json.prune
scala> j: play.api.libs.json.JsResult[play.api.libs.json.JsObject] = JsSuccess({"field2":{"num2":2,"text":"value","num":1},"field1":"value1"},/num2)

然后你可以使用你的Reads[Field1]

相关内容

  • 没有找到相关文章

最新更新