假设我有一个案例类,其中包含以下设置:
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
键的名称编码为UUID
,同时保持其他字段(原始数据类型)的默认处理。
基本上我喜欢理解Place
中字段的格式链是UUID,而不必为DefaultFormats
已经可以处理的所有字段指定AST结构。
我特别想要的是模仿类似JSONEncoder
and JSONDecoder
interfaces in python的模式,它可以使用键名和值类型来确定如何处理该字段的编组。
答案 0 :(得分:11)
现在在json4s的extras包中提供了一个UUID序列化程序。它很可能在版本3.2.11中提供(在撰写本文时尚未发布)。
你可以做这样的事情:
import org.json4s.ext.JavaTypesSerializers
implicit val json4sFormats = Serialization.formats(NoTypeHints) ++ JavaTypesSerializers.all
答案 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