如果我错了,请纠正我,但是当使用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隐式,这是一个非常强大的特性,可以使该机制高度可插拔,在某种意义上,此时您调用:Json.toJson(Location(4.5, 5.3))
编译器将在作用域中查找与所需类型匹配的隐式。Scala语言规范描述了解析隐式的算法,这种算法的设计方式是可以在有限的范围内"导入"隐式。由于这个特性,在程序的不同部分,你可以使读/写或任何类型类的不同实现可见。
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库集成,所以我以JSON通过Jackson/Spring集成为例。我相信它利用了Java Beans字段命名约定。这将涉及到在运行时发生的反射。
但是,Play的Scala Json库提供了Json数据中所有类型的编译时安全性。它也给了你一个很好的函数语法map
, flatMap
, orElse
等。这是一个巨大的优势。
查看更多信息:
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)
但是在播放Json的情况下,它不会工作,因为Json。format[T]是一个宏,它不能解析泛型符号T。它只能解析直接引用case类或任何带有unapply的符号。
另一方面,似乎可以编写一个宏来生成与我描述的相同的函数,但不是Apply(Json.format[T]),而是使用来自JsMacroImpl的AST。macroImpl(c, "format",…)。
无论如何,这不是语言限制-它只是没有在给定的库中实现。