4

我正在尝试通过像这样使用plays json库来更改此功能的实现

def apply[T](action: => ApiResponse[T])(implicit tjs: Writes[T], ec: ExecutionContext): Future[Result] = {
    action.fold(
      err =>
        Status(err.statusCode) {
          JsObject(Seq(
            "status" -> JsString("error"),
            "statusCode" -> JsNumber(err.statusCode),
            "errors" -> Json.toJson(err.errors)
          ))
        },
      t =>
        Ok {
          JsObject(Seq(
            "status" -> JsString("ok"),
            "response" -> Json.toJson(t)
          ))
        }
    )
  }

像这样使用 argonaut

def apply[T](action: => ApiResponse[T])(implicit encodeJson: EncodeJson[T], ec: ExecutionContext): Future[Result] = {
    action.fold(
      err =>
        Status(err.statusCode) {
          Json(
          "status" -> jString("error"),
          "statusCode" -> jNumber(err.statusCode),
          "errors" -> err.errors.asJson
          )
        },
      t =>
        Ok {
          Json(
          "status" -> jString("ok"),
          "response" -> t.asJson
          )
        }
    )
  }

但我明白了

无法将 argonaut.Json 的实例写入 HTTP 响应。尝试定义一个 Writeable[argonaut.Json]

对于 Status{} 块和 Ok{} 块,我在这里得到了这个问题的有用答案https://groups.google.com/forum/#!topic/play-framework/vBMf72a10Zc

所以我尝试像这样创建隐式转换

implicit def writeableOfArgonautJson(implicit codec: Codec): Writeable[Json] = {
      Writeable(jsval => codec.encode(jsval.toString))
    }

我认为将 json 对象转换为字符串并将其提供给 codec.encode 应该将其转换为 Array[Bytes] 但我得到了

无法猜测用于 argonaut.Json 的内容类型。尝试定义一个 ContentTypeOf[argonaut.Json]

jsval.nospaces.getBytes 也返回 Array[Bytes] 所以我不知道这是否可以用来提供帮助

所以虽然我认为最后一条错误消息意味着我只需要告诉 play 它应该使用内容类型 application.json 我也觉得这可能是一个不必要的兔子洞,应该有一个更简单的方法来做到这一点。

编辑:它不是一个兔子洞,因为定义 contentType 至少可以编译,但我仍然想知道这是否正确

4

1 回答 1

3

您似乎已经回答了自己的问题,但要确认的Writable[A]是:

  1. 如何将类型转换AArray[Bytes]
  2. 在响应中使用什么内容类型,这也需要
  3. 当前字符编码

字符编码由隐式Codec实例处理,因此您需要一个隐式ContentTypeOf[A]where Ais argonaunt.Json

implicit def contentTypeOf_ArgonautJson(implicit codec: Codec): ContentTypeOf[argonaut.Json] = {
  ContentTypeOf[argonaut.Json](Some(ContentTypes.JSON))
}

然后是Writable[A],它有一个类型约束A即有一个范围内ContentTypeOf[A](您刚刚定义):

implicit def writeableOf_ArgonautJson(implicit codec: Codec): Writeable[argonaut.Json] = {
  Writeable(jsval => codec.encode(jsval.toString))
}

正如你所指出的,兔子洞就这样结束了。Ok(myArgonautObject)事实上,当您考虑现在可以在没有进一步转换和标头设置样板的情况下执行任意数量的操作时,这肯定看起来有点转移,但没有太多额外的代码。

也许您可以将这些隐含在ExtraJsonHelpers特征中并将其混合到您的控制器中,以减少更多样板文件。

于 2015-02-01T16:05:12.133 回答