如何在lift-json中使用自定义序列化程序为类添加类型提示?

时间:2016-10-08 10:49:50

标签: lift-json

我们有一个现有的类A,它以前是唯一可以出现在REST API端点的JSON输出中某个位置的类型。但是,我现在正在扩展一个公共基类B,以便所有继承自B的不同类型都可以出现在输出中的该位置。

我在Formats添加了一个类型提示,但即使Formats方法在两个方向上正确查找了类型提示信息,也会在lift-json序列化时忽略类型提示。 / p>

原来,lift-json没有将类型提示字段添加到JSON的原因是因为在我们的Formats实例中还为该类配置了自定义序列化程序,并且自定义序列化程序覆盖了类型提示

那么我们怎样才能拥有一个既有自定义序列化程序的类,又发出并生成类型提示以允许明确标识其类型(在客户端和服务器上)?

1 个答案:

答案 0 :(得分:0)

这已经不是很好了,但TypeHints特征有两种方法:

def deserialize: PartialFunction[(String, JObject), Any] = Map()
def serialize: PartialFunction[Any, JObject] = Map()

在实现TypeHints特征(或扩展提供的TypeHints的默认实现)时,可以覆盖这些方法,以指定具有指定类型提示的JSON对象的自定义序列化和反序列化逻辑。默认实现(如上所示)实际上是部分函数,​​它们从不匹配任何东西,所以它们没有任何效果。

deserialize中的serializeSerializer方法存在一些差异,这是我们的代码以前使用的方法:

  1. 这些方法不会使用Formats参数,这意味着必须依赖范围内的Formats实例。

  2. 它们在转换的JSON端JObject上运行,而不是它的超类型JValue(显然,当你想到它时 - 因为任何有类型提示的东西都必然是一个JSON对象,不是字符串或数字或其他)。

  3. 他们不接受类型参数,只是在转换的Scala端对Any进行操作 - 这是因为他们只处理需要自定义序列化逻辑的所有类型提示类型大部分功能。

  4. TypeInfo部分函数取代deserialize而不是String,这是类型提示字段的值。

  5. 我认为大多数这些差异是因为这是较早的lift-json代码,从Serializer特征存在之前,以及只有一种方法可以进行自定义序列化。

    那对我有用的是:

    def typeHints(implicit formats: Formats) = new OurTypeHintsImpl( ... 输入提示信息 ... ) {

    override def deserialize = {

    case ("type-hint-for-A", o: JObject) => ... 现有的反序列化代码 ...

    }

    override def deserialize = {

    case A( ... ) => ... 现有序列化代码 ...

    }

    并添加另一个包含类型提示和自定义序列化逻辑的类型,只需要在上述两个中添加一个新的case分支。

    使用这种方法,lift-json会自动添加正确的类型提示,但您仍然可以完全自定义其余序列化和反序列化的完成方式。所以我认为对大多数情况来说这是最方便和最合适的方法(但确实需要一些重构)。还应该可以在自定义Serializer中重新实现类型提示,但为什么要重新发明轮子?

    警告:类型上的大小写匹配在默认情况下对泛型类型有限制,但这通常不应该用于此目的 - 除非您没有独立地序列化包含在另一种类型中的泛型类型,而是将其合并到JSON中的外部类型。