为什么在java中你不需要创建这些json读/写?

如果我错了,请纠正我,但是当使用Java而不是Spring MVC时,您不必创建这些额外的类来将Java类映射到JSON,将JSON映射到类。

你为什么要在Play with Scala中这样做? 它与Scala有关吗?

case class Location(lat: Double, long: Double) implicit val locationWrites: Writes[Location] = ( (JsPath \ "lat").write[Double] and (JsPath \ "long").write[Double] )(unlift(Location.unapply)) implicit val locationReads: Reads[Location] = ( (JsPath \ "lat").read[Double] and (JsPath \ "long").read[Double] )(Location.apply _) 

您必须在Play中执行此操作的原因是框架设计选择 ,这是一个非常好的选择。

在Play中,该机制依赖于Scala implicits ,这是一个非常强大的function,可以使机制高度可插拔 ,在您调用的那一刻:

 Json.toJson(Location(4.5, 5.3)) 

编译器将查找与所需类型匹配的隐式范围。 Scala语言规范描述了解决implicits的算法,并且这种算法的设计方式使您可以在有限范围内“ 导入 ”隐式。 由于这个function,在程序的不同部分,您可以看到您的读/写或任何类型类的不同实现。

 object MyImplicits { object ImplicitJson1{ implicit val write:Write[Location] = "write to json all fields" } object ImplicitJson2{ implicit val write:Write[Location] = "skip field a" } } object MyBusinessCode{ def f1(location:Location){ import MyImplicits.ImplicitJson1._ Json.toJson(location) } def f2(location:Location){ import MyImplicits.ImplicitJson2._ Json.toJson(location) } def dynamicChoice(location:Location){ implicit val write = { if(location.isEurope) MyImplicits.ImplicitJson1.write else MyImplicits.ImplicitJson2.write } Json.toJson(location) } } 

相反,在Spring中,这通常是通过内省和反思来完成的。 您可能需要使用注释来帮助Spring确定如何从数据模型构建Json。 结果是你不能改变它的完成方式,因此你的灵活性较低。

由于您可能不需要更多灵活性,因此许多Scala库/框架为您提供了生成所需类型类的默认实现的函数。 额外的代码行

 implicit val fmt = Json.format[Location] 

是你必须支付的价格,因为Play json序列化依赖于隐含。

你不需要:

 case class Location(lat: Double, long: Double) object Location { implicit val fmt = Json.format[Location] } Json.toJson(Location(4.5, 5.3)) // returns JsValue 

当您的JSON结构与您的对象定义不匹配时,手写的读/写/格式非常有用。

既然你没有提到你想要的JSON / Spring库集成,我就是通过Jackson / Spring集成来举例说明JSON。 我相信它利用了Java Beans字段命名约定。 这将涉及reflection,并且在运行时发生。

但是,Play的Scala Json库提供了JSON数据中所有类型的编译时安全性。 它还为您提供了一个很好的function语法mapflatMaporElse等。这是一个巨大的优势。

有关更多信息,请参阅此问

https://softwareengineering.stackexchange.com/questions/228193/json-library-jackson-or-play-framework

从理论上讲,可以用默认的隐式参数来编写函数

 def toJson[T](x: T)(implicit fmt: Reads[T] = Json.format[T]) = Json.toJson(x)(fmt) 

但是在Play Json的情况下,它将无法工作,因为Json.format [T]是一个宏,它无法解析generics类型符号T.它只能解析直接引用case类的符号或任何unapply(参见源代码 )

另一方面,似乎可以编写一个宏,它生成与我描述的相同的function,但代替Apply(Json.format [T])使用来自JsMacroImpl.macroImpl的 AST(c,“format”,…) 。

无论如何,它不是语言限制 – 它只是没有在给定的库中实现。