Custom Json使用组合子写入-不需要case类的所有字段



我正试图为case类编写一个自定义Json序列化程序,但我不希望它序列化该类的所有字段。我对Scala还很陌生,所以这肯定是问题所在,但这就是我迄今为止所尝试的:

case class Foo(a: String, b: Int, c: Double)

现在,就我在示例中看到的,默认的方法是:

implicit val fooWrites: Writes[Foo] = (
  (__  "a").write[String] and
  (__  "b").write[Int]
  (__  "c").write[Double]
) (unlift(Foo.unapply))

但是,如果我想从Json输出中省略"c"呢?到目前为止,我已经尝试过了,但它没有编译:

implicit val fooWritesAlt: Writes[Foo] = (
  (__  "a").write[String] and
  (__  "b").write[Int]
) (unlift({(f: Foo) => Some((f.a, f.b))}))

非常感谢您的帮助!

如果您正在使用Playframework 2.2(不确定早期版本,但它应该也能工作),请尝试以下操作:

implicit val writer = new Writes[Foo] {
  def writes(foo: Foo): JsValue = {
    Json.obj("a" -> foo.a,
             "b" -> foo.b)
  }
}

我通常要做的是将字段转换为None并在其上使用writeNullable:

implicit val fooWrites: Writes[Foo] = (
  (__  "a").write[String] and
  (__  "b").write[Int]
  (__  "c").writeNullable[Double].contramap((_: Double) => None)
) (unlift(Foo.unapply))

不必指定产生OWrites实例的组合子,也可以直接构造OWrites:

val ignore = OWrites[Any](_ => Json.obj())
implicit val fooWrites: Writes[Foo] = (
  (__  "a").write[String] and
  (__  "b").write[Int] and
  ignore
) (unlift(Foo.unapply))

这将忽略位于该位置的case类的任何值,并始终返回一个空的JSON对象。

使用Play的JSON转换器很容易做到这一点:

val outputFoo = (__  'c).json.prune

然后将transform(outputToo)应用于现有JsValue:

  val foo: Foo
  val unprunedJson: JsValue = Json.toJson(foo)
  unprunedJson.transform(outputFoo).map { jsonp =>
    Ok(Json.obj("foo" -> jsonp))
  }.recoverTotal { e =>
    BadRequest(JsError.toFlatJson(e))
  }

看这里http://mandubian.com/2013/01/13/JSON-Coast-to-Coast/

您使用的是什么版本的Play?fooWritesAlt使用2.1.3为我编译。需要注意的一点是,我需要显式地使用writes对象来编写部分JSON对象,即

fooWritesAt.writes(Foo("a", 1, 2.0))

返回

{"a": "a", "b": 2}

最新更新