如何交换JSON Writes Converter for Play控制器Action

时间:2016-10-12 22:20:18

标签: scala playframework

我已经使用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)
}

1 个答案:

答案 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)