组合类型和字段序列化程序

时间:2014-04-24 19:08:34

标签: json scala json4s

假设我有一个案例类,其中包含以下设置:

case class Place(id:java.util.UUID, name:String)

我可以为这种类型编写一个(working!)序列化程序,如下所示:

class placeSerializer extends CustomSerializer[Place]( format => (
        {
            case JObject(JField("id", JString(s)) :: JField("name",JString(x)) :: Nil ) =>
                Place(UUID.fromString(s), x)
        },
        {
            case x:Place =>
                JObject(
                  JField("id", JString(x.id.toString())) :: 
                  JField("name", JString(x.name)) :: Nil)
        }
        )
    )

但是假设我的case类最终有很多字段,这可能导致我用AST枚举对象的整个结构,创建一些非常详细的东西来编码基元。

json4s似乎具有只能在特定字段上起作用的字段序列化程序,其中包含样板方法以轻松转换名称和丢弃字段。但是,它们的serializedeserialize部分函数具有以下签名:

case class FieldSerializer[A: Manifest](
  serializer:   PartialFunction[(String, Any), Option[(String, Any)]] = Map(),
  deserializer: PartialFunction[JField, JField] = Map()
)

由于JField(代表键的类型 - 来自json的> val)是它自己的类型而不是JValue的子类,我如何才能正确地将这两种类型的序列化器合并到一起将id键的名称编码为UUID,同时保持其他字段(原始数据类型)的默认处理。

基本上我喜欢理解Place中字段的格式链是UUID,而不必为DefaultFormats已经可以处理的所有字段指定AST结构。

我特别想要的是模仿类似JSONEncoder and JSONDecoder interfaces in python的模式,它可以使用键名和值类型来确定如何处理该字段的编组。

2 个答案:

答案 0 :(得分:11)

现在在json4s的extras包中提供了一个UUID序列化程序。它很可能在版本3.2.11中提供(在撰写本文时尚未发布)。

你可以做这样的事情:

import org.json4s.ext.JavaTypesSerializers

implicit val json4sFormats = Serialization.formats(NoTypeHints) ++ JavaTypesSerializers.all

这是from the tests for this feature's PR

答案 1 :(得分:5)

诀窍是不要为你的类型编写一个序列化程序,而是编写你在里面使用的类型(在这种情况下是java.util.UUID)

然后您可以将该序列化程序添加到工具箱中,然后使用UUID的任何类型都将使用DefaultSerializer支持的字段完全类似:

case object UUIDSerialiser extends CustomSerializer[UUID](format => (
    {
      case JString(s) => UUID.fromString(s)
      case JNull => null
    },
    {
      case x: UUID => JString(x.toString)
    }
  )
)

implicit val json4sFormats = Serialization.formats(NoTypeHints) + UUIDSerialiser

更新指向the PR

的链接

更新2 PR已合并,现在,如果是UUID,您可以使用:

import org.json4s.ext.JavaTypesSerializers

implicit val json4sFormats = Serialization.formats(NoTypeHints) ++ JavaTypesSerializers.all