如何在 lift-json 中使用自定义序列化程序为 class 添加类型提示?
How to add type hints for class with custom serializer in lift-json?
我们有一个现有的 class A
,它以前是唯一可以出现在我们的 REST API 端点的 JSON 输出中特定位置的类型.但是,我现在让它扩展一个公共基础 class B
,以便一系列不同类型(全部继承自 B
)可以出现在输出中的那个位置。
我向 Formats
添加了类型提示,但即使 Formats
方法正确地双向查找了类型提示信息,在 lift-[ 序列化时忽略了类型提示=32=].
事实证明,lift-json 没有将类型提示字段添加到 JSON 的原因是因为还为 class 配置了一个自定义序列化程序我们的 Formats
实例和自定义序列化程序覆盖类型提示。
那么我们怎样才能拥有一个 class 既有自定义序列化程序,又能发出和生成类型提示以允许其类型被明确识别(在客户端和服务器上)?
这不再是很好的记录,但 TypeHints
特征有两种方法:
def deserialize: PartialFunction[(String, JObject), Any] = Map()
def serialize: PartialFunction[Any, JObject] = Map()
这些方法可以在实现 TypeHints
特性(或扩展提供的 TypeHints
的默认实现)时被覆盖,以指定自定义序列化和反序列化逻辑 JSON 对象具有指定的类型提示。默认实现(如上所示)只是有效的部分函数,它从不匹配任何东西,所以它们没有任何效果。
Serializer
中的 deserialize
和 serialize
方法有一些不同,这是我们的代码之前使用的方法:
这些方法不接受 Formats
参数,这意味着必须依赖范围内的 Formats
实例。
它们在转换的 JSON 侧对 JObject
进行操作,而不是它的超类型 JValue
(很明显,当你考虑它时 - 因为任何具有类型提示的必然是 JSON 对象,而不是字符串或数字或其他任何东西)。
它们不接受类型参数,只是在转换的 Scala 端对 Any
进行操作——这是因为它们只处理所有需要自定义的类型提示类型一个大的偏函数中的序列化逻辑。
TypeInfo
而不是 deserialize
部分函数采用 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 会自动添加正确的类型提示,但您仍然可以完全自定义其余序列化和反序列化的完成方式。所以我认为它是大多数情况下最方便和最合适的方法(但它确实需要一些重构)。也应该可以在自定义中重新实现类型提示 Serializer
,但为什么要重新发明轮子?
警告:默认情况下,类型上的大小写匹配对泛型类型有限制,但这通常不会影响此目的 - 除非您不是独立序列化包含在另一个类型中的泛型类型,而是合并它变成了 JSON.
中的外部类型
我们有一个现有的 class A
,它以前是唯一可以出现在我们的 REST API 端点的 JSON 输出中特定位置的类型.但是,我现在让它扩展一个公共基础 class B
,以便一系列不同类型(全部继承自 B
)可以出现在输出中的那个位置。
我向 Formats
添加了类型提示,但即使 Formats
方法正确地双向查找了类型提示信息,在 lift-[ 序列化时忽略了类型提示=32=].
事实证明,lift-json 没有将类型提示字段添加到 JSON 的原因是因为还为 class 配置了一个自定义序列化程序我们的 Formats
实例和自定义序列化程序覆盖类型提示。
那么我们怎样才能拥有一个 class 既有自定义序列化程序,又能发出和生成类型提示以允许其类型被明确识别(在客户端和服务器上)?
这不再是很好的记录,但 TypeHints
特征有两种方法:
def deserialize: PartialFunction[(String, JObject), Any] = Map()
def serialize: PartialFunction[Any, JObject] = Map()
这些方法可以在实现 TypeHints
特性(或扩展提供的 TypeHints
的默认实现)时被覆盖,以指定自定义序列化和反序列化逻辑 JSON 对象具有指定的类型提示。默认实现(如上所示)只是有效的部分函数,它从不匹配任何东西,所以它们没有任何效果。
Serializer
中的 deserialize
和 serialize
方法有一些不同,这是我们的代码之前使用的方法:
这些方法不接受
Formats
参数,这意味着必须依赖范围内的Formats
实例。它们在转换的 JSON 侧对
JObject
进行操作,而不是它的超类型JValue
(很明显,当你考虑它时 - 因为任何具有类型提示的必然是 JSON 对象,而不是字符串或数字或其他任何东西)。它们不接受类型参数,只是在转换的 Scala 端对
Any
进行操作——这是因为它们只处理所有需要自定义的类型提示类型一个大的偏函数中的序列化逻辑。TypeInfo
而不是deserialize
部分函数采用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 会自动添加正确的类型提示,但您仍然可以完全自定义其余序列化和反序列化的完成方式。所以我认为它是大多数情况下最方便和最合适的方法(但它确实需要一些重构)。也应该可以在自定义中重新实现类型提示 Serializer
,但为什么要重新发明轮子?
警告:默认情况下,类型上的大小写匹配对泛型类型有限制,但这通常不会影响此目的 - 除非您不是独立序列化包含在另一个类型中的泛型类型,而是合并它变成了 JSON.
中的外部类型