json - 创建一个通用的 Json 序列化函数

标签 json scala generics playframework playframework-2.2

是否可以使用 Play Framework 2.2 在 Scala 中创建一个通用函数,将任意对象序列化为 JSON,而无需提供编写器或格式化程序?

例如,这个非通用代码将创建一个给定客户的 JSON 响应:

import play.api.libs.json._
import play.api.libs.functional.syntax._

case class Customer(id: Int, name: String)

object scratch {
  val p = Customer(1, "n")                        
  //> p  : Customer = Customer(1,n)

  def createJsonResponseCustomer(data: Customer) = {
    implicit val formatter = Json.format[Customer]
    Json.obj("success" -> true, "data" -> Json.toJson[Customer](data))
  }

  createJsonResponseCustomer(p)                   
  //> res0: play.api.libs.json.JsObject = {"success":true,"data":{"id":1,"name":"n"}}
}

为了避免必须为每个不同的对象定义格式化程序,我想创建一个这样的通用函数:
def createJsonResponse[T](data: T) = {
  implicit val formatter = Json.format[T]
  Json.obj("success" -> true, "data" -> Json.toJson[T](data))
}

但是这种尝试会产生错误 No unapply function foundJson.format[T] .

换句话说,这有效:
def getFormatter(c: Customer) = Json.format[Customer]

但这不是:
def getFormatterGeneric[T](c: T) = Json.format[T]

有没有办法解决?

最佳答案

您需要在某处为您希望读取或写入的每种类型定义格式化程序。这是因为格式化程序实例是在编译时解析的,而不是在运行时解析的。这是一件好事,因为这意味着尝试序列化没有序列化程序的类型会成为编译时错误,而不是运行时错误。

与其动态定义格式化程序,不如在可以重用的模块中定义它们,例如

object JsonFormatters {
  implicit val customerWrites: Format[Customer] = Json.format[Customer]
}

然后import JsonFormatters._在您要编写一些 JSON 的范围内。

现在,您可以编写一个类似于您想要的通用方法:您只需在方法的签名中指定对格式化程序的要求。实际上,这是 Writes[T] 类型的隐式参数。 .
def createJsonResponse[T](data: T)(implicit writes: Writes[T]) =
  Json.obj("success" -> true, "data" -> Json.toJson[T](data))

您还可以使用上下文绑定(bind)语法编写此方法签名,即
def createJsonResponse[T : Writes](data: T) = ...

这要求有 Writes[T] 的实例在适用范围;但编译器会根据类型 T 为您选择正确的实例,而不是你明确地解决它。

请注意 Writes[T]Format[T] 的父类(super class)型;由于您只是在此方法中编写 JSON,因此无需指定 Format[T] 的要求,这也会给你Reads[T] .

关于json - 创建一个通用的 Json 序列化函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19611361/

相关文章:

Java 枚举和泛型

json - 查询 jsonb 数组

arrays - 在Scala中将两个数组与索引一起压缩?

swift - 如何为通用 Result<T> 类型定义相等性?

scala - IntelliJ 无法导入 sbt 项目

eclipse - Scala IDE 无法解析依赖关系

c# - 为 MemoryCache(或任何缓存)实现通用 Get<T>

c++ - 从MAP中的C++文件中读取键值对(Json格式)

javascript - 从JSON响应中过滤ng-repeat

javascript - ajax请求后 undefined variable