3

我有一个案例类Game,使用json4s序列化/反序列化没有问题。

case class Game(name: String,publisher: String,website: String, gameType: GameType.Value)

在我的应用程序中,我使用mapperdao作为我的 ORM。因为Game使用了代理 ID,所以我没有id它的构造函数的一部分。

然而,当 mapperdao 从数据库返回一个实体时,它使用一个特征提供持久对象的 id。

Game with SurrogateIntId

特征的代码是

trait SurrogateIntId extends DeclaredIds[Int]
{
    def id: Int
}

trait DeclaredIds[ID] extends Persisted

trait Persisted
{
    @transient
    private var mapperDaoVM: ValuesMap = null
    @transient
    private var mapperDaoDetails: PersistedDetails = null
private[mapperdao] def mapperDaoPersistedDetails = mapperDaoDetails

private[mapperdao] def mapperDaoValuesMap = mapperDaoVM

private[mapperdao] def mapperDaoInit(vm: ValuesMap, details: PersistedDetails) {
    mapperDaoVM = vm
    mapperDaoDetails = details
}
.....
}

当我尝试序列化时Game with SurrogateIntId,返回空括号,我认为这是因为 json4s 不知道如何处理附加的特征。

我需要一种gameid添加到其属性T with SurrogateIntId的序列化方法,并且几乎与对所有域对象都使用这些方法一样重要的方法是为任何对象执行此操作。

谁能帮我吗?

4

1 回答 1

1

所以这是一个非常具体的解决方案,因为我的问题的根源来自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(或两者)来找到更简单的解决方案。但是,就目前而言,这似乎是开销最少的修复方法。

于 2014-09-17T14:32:27.760 回答