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

Dea*_*ado 12 json scala json4s

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

case class Place(id:java.util.UUID, name:String)
Run Code Online (Sandbox Code Playgroud)

我可以为这种类型编写一个(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)
        }
        )
    )
Run Code Online (Sandbox Code Playgroud)

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

json4s似乎具有只能在特定字段上起作用的字段序列化程序,其中包含样板方法以轻松转换名称和丢弃字段.然而,这些对他们的以下签名serializedeserialize部分功能:

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

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

基本上我想要一个理解其中的字段的格式链Place是一个UUID,而不必为所有DefaultFormats已经处理的字段指定AST结构.

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

Jus*_*tin 11

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

你将能够做这样的事情:

import org.json4s.ext.JavaTypesSerializers

implicit val json4sFormats = Serialization.formats(NoTypeHints) ++ JavaTypesSerializers.all
Run Code Online (Sandbox Code Playgroud)

这是从该功能的PR的测试中获得的.


iwe*_*ein 6

诀窍是不为您的类型编写序列化程序,而是为您在其中使用的类型(在本例中为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
Run Code Online (Sandbox Code Playgroud)

更新PR的链接

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

import org.json4s.ext.JavaTypesSerializers

implicit val json4sFormats = Serialization.formats(NoTypeHints) ++ JavaTypesSerializers.all
Run Code Online (Sandbox Code Playgroud)