【问题标题】:Write an Arbitrary Value Not Found in a Case Class Using Play's (2.2) Scala JSON Combinators使用 Play 的 (2.2) Scala JSON 组合器编写在案例类中未找到的任意值
【发布时间】:2014-04-11 17:57:33
【问题描述】:

我想实现一个Writes,它发出一个在被序列化的类中找不到的 JSON 对象。

案例类:

case class Foo(i:Int, s:String)

我正在寻找制作:

{
  "i": <int>,
  "s": "<string>",
  "other": "Some value."
}

天真的第一次尝试是:

val writes: Writes[Foo] = ((
  (__ \ "i").write[Int] and
    (__ \ "s").write[String] and
    (__ \ "other").write("Some value.")
  )(unlift(Foo.unapply))

当然,这不会编译,因为随后的 and 调用会产生 CanBuild3Foounapply 会产生 Tuple2。我曾考虑在结果中附加一个值,生成一个Tuple3,但我发现looks pretty badlanguage maintainers will not implement it

有一些方法可以解决这个问题,但我不想用我想添加到结果 JSON 中的这些装饰器值污染我的模型类。

有什么建议吗?

值得注意的是,您可以走另一个方向,在 JSON 中不存在值但由结果对象指定的情况下,使用 Reads.pure 提供值。

【问题讨论】:

    标签: json scala playframework functional-programming combinators


    【解决方案1】:

    你可以通过脱糖很直接地做到这一点:

    val writes: Writes[Foo] = (
      (__ \ "i").write[Int] and
      (__ \ "s").write[String] and
      (__ \ "other").write[String]
    )(foo => (foo.i, foo.s, "Some value."))
    

    unlift(Foo.unapply) 只是将函数从 Foo 获取到前面应用构建器表达式所需类型的元组的一种奇特方式,您可以将其替换为您自己的函数,该函数可以添加您想要的任何内容.

    如果你真的想要更简洁的语法,你可以使用Shapeless:

    import shapeless.syntax.std.tuple._
    
    val writes: Writes[Foo] = (
      (__ \ "i").write[Int] and
      (__ \ "s").write[String] and
      (__ \ "other").write[String]
    )(_ :+ "Some value.")
    

    它很漂亮,但可能有点矫枉过正。

    【讨论】:

    • 好建议!第一个是一个想法,但它变得更加难以与更高的arity产品一起使用。那好吧。如果 Shapeless 语法如此简单——而且该库对生产有好处——那么我将尝试使用它。感谢您的帮助!
    【解决方案2】:

    另一种选择是使用一个对象构建器,它实现了一个返回额外值的unapply。这使 Writes 更清晰,但添加了一个新对象。我发现这很有用,因为 apply 和 unapply 方法都可以用于将数据额外按摩到最终对象中(例如:https://stackoverflow.com/a/22504468/1085606

    例子:

    case class Foo(i: Int, s: String)
    
    object FooBuilder {
      def unapply(foo: Foo): Option[(Int, String, String)] = {
        Some((foo.i, foo.s, "Some extra value"))
      }
    }
    
    val writes: Writes[Foo] = ((
      (__ \ "i").write[Int] and
        (__ \ "s").write[String] and
        (__ \ "other").write[String]
      )(unlift(FooBuilder.unapply))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-08-23
      • 1970-01-01
      • 1970-01-01
      • 2018-02-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多