所以这是一个非常具体的解决方案,因为我的问题的根源来自mapperDao返回 DO 的方式,但是它可能对一般用途有所帮助,因为我正在研究json4s 中的自定义序列化程序。
关于这个问题的完整讨论可以在 mapperDao google group 上找到。
首先,我发现调用copy()
任何持久化实体(从 mapperDao 返回)返回了我的 DO 的干净副本(只是案例类)——然后它可以由 json4s 序列化。但是,我不想记住在copy()
任何时候我想序列化 DO 或处理映射列表等时调用,因为这会很笨重并且容易出错。
因此,我创建了一个CustomSerializer
包装返回的实体(案例类 DO + 特征作为对象),并使用隐式清单从泛型类型中收集类。使用这种方法,我然后对我的域对象进行模式匹配以确定传入的内容,然后用于Extraction.decompose(myDO.copy())
序列化并返回干净的 DO。
// Entity[Int, Persisted, Class[T]] is how my DOs are returned by mapperDao
class EntitySerializer[T: Manifest] extends CustomSerializer[Entity[Int, Persisted, Class[T]]](formats =>(
{PartialFunction.empty} //This PF is for extracting from JSON and not needed
,{
case g: Game => //Each type is one of my DOs
implicit val formats: Formats = DefaultFormats //include primitive formats for serialization
Extraction.decompose(g.copy()) //get plain DO and then serialize with json4s
case u : User =>
implicit val formats: Formats = DefaultFormats + new LinkObjectEntitySerializer //See below for explanation on LinkObject
Extraction.decompose(u.copy())
case t : Team =>
implicit val formats: Formats = DefaultFormats + new LinkObjectEntitySerializer
Extraction.decompose(t.copy())
...
}
唯一需要一个单独的序列化程序是在您将非基元作为正在序列化的案例类的参数的情况下,因为序列化程序不能使用自己进行序列化。在这种情况下,您为每个基本类创建一个序列化程序(即只有原语的 IE),然后将其包含到下一个序列化程序中,其中包含依赖于这些基本类的对象。
class LinkObjectEntitySerializer[T: Manifest] extends CustomSerializer[Entity[Int, Persisted, Class[T]]](formats =>(
{PartialFunction.empty},{
//Team and User have Set[TeamUser] parameters, need to define this "dependency"
//so it can be included in formats
case tu: TeamUser =>
implicit val formats: Formats = DefaultFormats
("Team" -> //Using custom-built representation of object
("name" -> tu.team.name) ~
("id" -> tu.team.id) ~
("resource" -> "/team/") ~
("isCaptain" -> tu.isCaptain)) ~
("User" ->
("name" -> tu.user.globalHandle) ~
("id" -> tu.user.id) ~
("resource" -> "/user/") ~
("isCaptain" -> tu.isCaptain))
}
))
这个解决方案很难令人满意。最终我将需要替换 mapperDao 或 json4s(或两者)来找到更简单的解决方案。但是,就目前而言,这似乎是开销最少的修复方法。