使用/ Tuple为Case类定义Writes [...]

时间:2014-06-22 19:40:37

标签: scala playframework-2.0

鉴于此范围类:

case class Range(things: (String, String))

我尝试在Writes[Range]上的Play Json docs示例中实现Creature

implicit val rangeWrites: Writes[Range] =
  (JsPath \ "things").write(
    (JsPath \ "string").write[String] and
    (JsPath \ "string").write[String]
      tupled
  )(unlift(Range.unapply))

然而,我得到了:

[error] JsonTest.scala 19 could not find implicit value for 
        parameter app: play.api.libs.functional.
                                 Applicative[play.api.libs.json.OWrites]
[error]       (JsPath \ "items").write(

如何正确填写(JsPath \ "items").write(?在文档的示例中,似乎没有任何类型需要。

2 个答案:

答案 0 :(得分:3)

此处的问题与this question中显示的问题非常类似:您无法在普通的Writes(或OWrites)上使用适用语法 - 您需要Builder

此处的解决方案也类似,但您需要map而不是contramap,因为Writes是一个逆变函子,而不是仿函数:

implicit val rangeWrites: Writes[Range] =
  (JsPath \ "things").write(
    (JsPath \ "string1").write[String] and
    (JsPath \ "string2").write[String]
      tupled
  ).contramap(unlift(Range.unapply))

另请注意,我已将密钥更改为string1string2 - 如果您使用相同的密钥,则无法获得预期效果。

答案 1 :(得分:1)

另一种方法是直接实现Writes trait,这样可以更好地控制对象如何转换为JSON。

示例:

    implicit object RangeWrites extends Writes[Range] {
    def writes(value: Range): JsValue = {
        Json.obj("things" -> Json.arr(value.things._1, value.things._2))
    }
}

为对象提供以下JSON:{"things":["hello","all"]}Range(("hello", "all"))