问题 结合类型和字段序列化程序


假设我有一个带有以下设置的案例类:

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似乎具有只能在特定字段上起作用的字段序列化程序,其中包含样板方法以轻松转换名称和丢弃字段。然而,这些具有以下签名 serialize 和 deserialize 部分功能:

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

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

基本上我想要一个理解其中的领域的格式链 Place 是一个UUID,无需为所有字段指定AST结构 DefaultFormats 已经可以处理了。

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


9815
2018-04-24 19:08


起源

没有评论的Downvotes让我伤心:( - DeaconDesperado
检查一下 stackoverflow.com/questions/23977779/... 针对UUID的具体问题 - iwein


答案:


诀窍是不要为你的类型编写一个序列化程序,而是为你在里面使用的类型(在这种情况下是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

更新 链接到 公关

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

import org.json4s.ext.JavaTypesSerializers

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

5
2018-06-01 08:07



谢谢@iwein!仍然习惯于暗示的魔力......很难打破旧的命令性习惯。 - DeaconDesperado
很高兴帮助@DeaconDesperado - iwein


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

你将能够做到这样的事情:

import org.json4s.ext.JavaTypesSerializers

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

这是采取的 从这个功能的PR的测试


11
2017-08-26 17:37



我喜欢它,当我的答案因合并我的拉动请求而过时了:)为好的发现+1,我希望你不介意我更新我的答案以反映新的现实。 - iwein
顺便说一下,测试的链接坏了,你可以像我一样链接到拉取请求: github.com/json4s/json4s/pull/130/files - iwein