scala - 使用 json4s 序列化带有特征混合的案例类

标签 scala serialization case-class traits json4s

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

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

在我的应用程序中,我使用 mapperdao作为我的 ORM。因为 Game 使用 Surrogate Id我没有 id 有其构造函数的一部分。

但是,当 mapperdao 从数据库返回一个实体时,它会使用特征提供持久化对象的 ID。

与 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
}
.....
}

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

我需要一种方法来序列化 game 并且只将 id 添加到它的属性 ,并且几乎同样重要的是为任何T with SurrogateIntId 因为我将它们用于我所有的域对象。

谁能帮帮我?

最佳答案

所以这是一个非常具体的解决方案,因为我的问题起源于 mapperDao 的方式返回 DO,但是它可能对一般用途有帮助,因为我正在研究 custom serializers在 json4s 中。

关于这个问题的完整讨论可以在found on the mapperDao google group .

首先,我发现在任何持久实体(从 mapperDao 返回)上调用 copy() 会返回我的 DO 的干净副本(只是 case 类)——然后可以由 json4s 序列化。但是,我不想在任何时候想要序列化 ​​DO 或处理映射列表等时都必须记住调用 copy(),因为这会很笨拙并且容易出错。

因此,我创建了一个 CustomSerializer,它环绕返回的实体(case class DO + traits as an object)并使用隐式 list 从泛型类型中收集类。使用这种方法,我然后对我的域对象进行模式匹配以确定传入的内容,然后使用 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())
...
}

唯一需要单独的序列化程序的情况是,如果您将非基元作为要序列化的案例类的参数,因为序列化程序无法使用自身进行序列化。在这种情况下,您为每个基本类(即只有基元的)创建一个序列化器,然后将其包含到下一个序列化器中,其中包含依赖于这些基本类的对象。

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(或两者)以找到更简单的解决方案。但是,就目前而言,它似乎是开销最少的修复方法。

关于scala - 使用 json4s 序列化带有特征混合的案例类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24961203/

相关文章:

java - Scala Spring Boot Autowiring 不起作用

scala - 使用 Scala 和 Dispatch 进行 HTTPS POST

c++ - 如何简单地序列化复杂结构并在 Qt 中通过网络发送它们

java - 测试类的序列化

scala - 为什么 Unit 不在 Scala 中扩展 Product?

json - Scala - 如何将 json 作为输入参数并解析它?

scala - 重命名并覆盖案例类中的 equals 方法

mysql - 如何将 Slick 3.1(Scala) 中的数据分成 4 部分

python - 如何返回用户名而不是 ID

scala - 回复不会传回 'client' -actor