如果我错了,请纠正我,但是当使用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 _)
答案 0 :(得分:11)
您必须在Play中执行此操作的原因是框架设计选择,这是一个非常好的选择。
在Play中,该机制依赖于 Scala implicits ,这是一个非常强大的功能,可以使机制高度可插入,从而在您调用的那一刻:
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序列化依赖于隐式。
答案 1 :(得分:1)
您不需要:
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结构与您的对象定义不匹配时,手写的读/写/格式非常有用。
答案 2 :(得分:1)
由于您还没有提到您想要的JSON / Spring库集成,我将通过Jackson / Spring集成来举例说明JSON。我相信它利用了Java Beans字段命名约定。这将涉及反射,并且在运行时发生。
但是,Play的Scala Json库提供了JSON数据中所有类型的编译时安全性。它还为您提供了一个很好的函数语法map
,flatMap
,orElse
等。这是一个巨大的优势。
更多信息请参阅此问题:
答案 3 :(得分:0)
理论上,可以使用默认隐式参数(如
)编写函数def toJson[T](x: T)(implicit fmt: Reads[T] = Json.format[T]) = Json.toJson(x)(fmt)
但是在Play Json的情况下,它将无法工作,因为Json.format [T]是一个宏,它无法解析泛型类型符号T.它只能解析直接引用case类的符号或任何unapply的符号(参见sources)
另一方面,似乎可以编写一个宏,它生成与我描述的相同的功能,但代替Apply(Json.format [T])使用来自JsMacroImpl.macroImpl的AST(c,&#34) ;格式",...)。
无论如何,它不是语言限制 - 它只是没有在给定的库中实现。