播放json解析缺少的字段为空数组

时间:2014-07-22 02:30:57

标签: json scala playframework

使用play-json 2.3 我该如何解析这个

{i: 0}

进入这个

case class A(i: Int, s: Seq[Int])

我非常想重用Json.format宏

目前它给了我"缺少路径"

UPD: 我最终写了一个自定义格式并将其拉到JsPath上:

implicit class JsPathExtensions(path: JsPath) {
  //return mzero if the path is missing
  def lazyFormatNullableM[T: Monoid](f: => Format[T]): OFormat[T] = OFormat(path.lazyReadNullable(f).map(_.orZero), new OWrites[T] {
    override def writes(o: T) = path.lazyWriteNullable(f).writes(o.some)
  })
}

2 个答案:

答案 0 :(得分:3)

如果缺少路径,我认为没有任何方法可以在不更改类的情况下使用宏。在这种情况下,您可以使用json组合器定义Reads并将宏用于Writes

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

implicit val reads: Reads[A] = (
    (__ \ "i").read[Int] and 
    (__ \ "s").read[Seq[Int]].orElse(Reads.pure(Nil))
)(A.apply _)

implicit val writes: Writes[A] = Json.writes[A]

json宏仅涵盖非常有限的用例范围,并且您不可避免地会遇到必须编写自己的ReadsWrites的情况。

答案 1 :(得分:2)

使用Json.format[A]宏的最简单方法是略微改变您对A的定义:

case class A(i: Int, s: Option[Seq[Int]])

此处Option的使用非常明确,您可以map覆盖它并做很多好事,但如果真的想要对待{{1}喜欢它是一个空集合,你可以更多地增强你的案例类:

s

现在,如果您访问case class Foo(i: Int, s: Option[Seq[Int]]) { lazy val theSeq:Seq[Int] = s.getOrElse(Seq[Int]()) } ,则省略theSeq的传入JSON与为s提供空数组的JSON之间绝对没有区别。