0

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

我在 中添加了类型提示Formats,但即使这些Formats方法在两个方向上都正确查找了类型提示信息,在 Lift-json 进行序列化时,类型提示也会被忽略。

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

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

4

1 回答 1

0

这不再有很好的记录,但是该TypeHints特征有两种方法:

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

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

deserialize中的和serialize方法有一些不同Serializer,这是我们之前的代码使用的:

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

  2. 它们在JObject转换的 JSON 端进行操作,而不是它的超类型JValue(显然,当您考虑它时 - 因为任何具有类型提示的东西都不可避免地必须是 JSON 对象,而不是字符串或数字或其他)。

  3. 它们不采用类型参数,只在Any转换的 Scala 端进行操作——这是因为它们只处理需要在一个大的部分函数中自定义序列化逻辑的所有类型提示类型。

  4. 代替 a TypeInfodeserialize偏函数采用 a String,它是类型提示字段的值。

我认为这些差异大部分是因为这是较旧的 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 会自动添加正确的类型提示,但您仍然可以完全自定义其余序列化和反序列化的完成方式。所以我认为它是大多数情况下最方便和最合适的方法(但它确实需要一些重构)。也应该可以在 custom 中重新实现类型提示Serializer,但为什么要重新发明轮子呢?

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

于 2016-10-08T10:49:49.543 回答