25

在 Scala 2.10 中,我们显然得到了改进的反射。

这将如何影响lift-json、jerkson、sjson 和朋友?此外,我们是否可以期待在不久的将来,内置的 JSON 语言功能就像 Groovy 在 Scala 中的出色 GSON?

我问的原因是我非常想做:

case class Foo(a: String, b: Int, bar: Bar)
case class Bar(c: Int)
val foo = Foo("hey", 10, Bar(23))
val json = foo.toJson

没有箍跳(即样板式的准备工作),即使是任意复杂的对象图。也许我问的太多了,但一个人总是可以梦想的。请粉碎我的 2.10 梦想,或者告诉我随着备受期待的 Scala 版本开辟了哪些新途径。下一个

此外,对于案例类,似乎对于验证/创建,scalaz 验证是首选武器。作为对象创建的安全代理或错误收集器,这看起来非常棒。然而,作为一名 Scewbie,我发现 scalaz 有点挑战性,尽管它具有明显的力量,但我仍在抵制 F-ing 黑暗面;-)

无论如何,这里的重点是,使用 2.10 反射,我们应该能够在运行时将表单帖子中的字段绑定到案例类的属性,并仅基于属性类型执行基本验证(即不会有指定单独的验证逻辑,指定属性 foo 必须是一个字符串,因为它的类型已经在我们现在可以正确反映的案例类中定义)

那么,勇敢的新世界来了,还是现有的工具是可预见的未来的中流砥柱?

4

3 回答 3

6

前言

让我给出一个不同的解决方案,它不依赖于任何基于 Java 的库,而只依赖于一个纯 Scala 库。

实际上,正如@Steve 的结果评论中所讨论的,Play 2 的 scala 版本正在使用 Jerkson 将 Json 反序列化为域模型。Jerkson 是一个 DSL 包装器,它围绕一个非常好的 Java 库来处理 Json。

回答

上面没有回答你的问题,因为你问的是是否已经设想使用 Scala 2.10 的反射和宏特性来简化这个任务!!!!通过消除大多数样板。

事实上这是一个非常好的想法,因为从 Play 2.1 版本开始,Json Scala API 不再使用 Jerkson,而是使用了自己的机制。

这种机制实际上是利用了这个新的 Scala 2.10 版本,引入了一个基于两件事的全新 API:

  • 一个功能构造(Applicative Builder),适用于能够读取和写入 Json 或 Domain 实例。这些构建器用于粘合所有组合器(用于读取或写入)以定义粗粒度结构(就像我们使用 Parser Combinators 所做的那样)
  • 一堆宏,它们能够发现哪些组合器是隐式可用的,并将为案例类(或至少具有applyunapply方法的类型)构造复杂的组合器。

归根结底,我们可以使用这个 API 做以下事情:

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

case class Person(name: String, age: Int, lovesChocolate: Boolean)

implicit val personReads = Json.format[Person] //a format is a Reader and a Writer

//this format will be implicitly used by the following from/toJson functions
val person:JsResult[Person] = Json.fromJson(json) //JsResult is like JsSucces/JsError
val jsObject = Json.toJson(person)

代码复制并改编自:JSON Inception(基于 Scala 2.10 宏)

一点提示:新的 API 甚至足够智能,能够通过累积错误来验证“读取”...

参考

我会从这里推荐来自@mandubian 的一系列博客,因为它们非常有启发性!

最后说明

可悲的是,Play 2 的模块化......不允许我们单独使用这个 API!所以,它应该从整个 play 库中使用:/ 这可能会在未来改变......

编辑

未来越来越近了,因为 Pascal 有这个repo使我们能够使用 play-json API。

因此,在 Play 2.2 发布之前,可以使用这个 repo。事实上,这个版本将与几个 API (如 json 或 iteratees)完全解耦,因此,我们将能够直接使用 playframework repo。

于 2013-01-02T21:48:41.077 回答
4

Jerkson今天处理您的用例!

Json.generate(foo)

它还支持我们在生产中广泛使用的流式读写。

Json.generate(foo, outputStream)
Json.parse[Foo](inputStream)

我们最初使用 lift-json,但它缺乏对案例类的流式支持,使其无法用于读取和写入大型 json 文档。Jerkson 的速度也非常快,可以完美地处理嵌套的案例类。

于 2012-03-18T14:15:53.830 回答
0

对此发表了一篇博客文章,请访问http://pedrorijo.com/blog/scala-json/

使用案例类和Play WS(已包含在 Play 框架中),您可以使用简单的单行隐式在 json 和案例类之间进行案例转换

case class User(username: String, friends: Int, enemies: Int, isAlive: Boolean)

object User {
  implicit val userJsonFormat = Json.format[User]
}
于 2016-01-05T20:33:45.243 回答