我已经使用Scala和Play构建了一个微服务,现在我需要创建一个新版本的服务,它返回与之前版本服务相同的数据,但采用不同的JSON格式。该服务当前使用隐式Writes转换器来执行此操作。我的控制器看起来像这样,其中MyJsonWrites包含隐式定义。
class MyController extends Controller with MyJsonWrites {
def myAction(query: String) = Action.async {
getData(query).map {
results =>
Ok(Json.toJson(results))
}
}
}
trait MyJsonWrites {
implicit val writes1: Writes[SomeDataType]
implicit val writes2: Writes[SomeOtherDataType]
...
}
现在我需要一个新版本的myAction,其中JSON的格式不同。我做的第一个尝试是使MyController成为一个基类,并让子类用它们自己的具有隐含值的特征扩展它。这样的事情。
class MyNewContoller extends MyController with MyNewJsonWrites
这不起作用,因为在MyNewJsonWrites上定义的隐式值在超类的方法中不可用。
如果我可以在控制器上创建一个新的动作,以某种方式使用MyNewJsonWrites中定义的转换器,那将是理想的。当然,我可以将特性更改为一个对象,并在每个方法中导入隐含值,但是我必须复制myAction的方法体,以便当我调用Json.toJson时,implicits在范围内。我不想将它们作为隐式参数传递给基本方法,因为它们太多了。我想我可以将一个方法作为参数传递给实际执行导入和Json.toJson调用的基本方法。像这样的东西。我只是觉得可能有更好的方式。
def myBaseAction(query: String, toJson: Seq[MyResultType] => JsValue) = Action.async {
getData(query).map {
results =>
Ok(Json.toJson(results))
}
}
def myActionV1(query: String) = {
def toJson(results: Seq[MyResultType]) = {
import MyJsonWritesV2._
Json.toJson(results)
}
myBaseAction(query, toJson)
}
答案 0 :(得分:1)
您可以直接调用您的写入,而不是依赖于scala隐式解析:
def myBaseAction(query: String, writes: Writes[MyResultType]) = Action.async {
getData(query).map { results =>
val seqWrites: Writes[Seq[MyResultType]] = Writes.seq(writes)
Ok(seqWrites.writes(results))
}
}
def myActionV1(query: String) = myBaseAction(query, MyJsonWritesV1)
def myActionV2(query: String) = myBaseAction(query, MyJsonWritesV2)