Serialization with Jackson

# Serialization with Jackson
# 依赖
要使用Jackson序列化,必须在项目中添加以下依赖项:
# 介绍
您可以在“序列化”部分中找到有关Akka序列化的概念。 本节描述如何使用Jackson序列化应用程序特定的消息、持久性事件和快照。

Jackson支持基于文本的JSON和二进制格式。

在许多情况下,Jackson可以对普通类进行序列化而无需任何其他提示,但是有时需要使用注释来指定如何将对象转换为JSON/字节。

# 用法
要为某个类启用Jackson序列化,您需要在序列化绑定配置中配置它或它的一个超类。 通常,您将为此创建一个标记器接口,并让消息实现该接口。
然后,在序列化绑定中将标记器接口的类名称配置为:jackson-json或jackson-cbor

一个好的约定是将标记接口命名为CborSerializable或JsonSerializable。在本文档中,我们使用MySerializable来明确表明Akka不提供标记接口本身。

这是Jackson理解结构的基础类所需要的。下面介绍了需要注释的几种情况。

请注意,只有顶级类或其标记接口必须在serialization-bindings定义,而不是它在成员字段中引用的嵌套类。

>注意
添加-parameters Java编译器选项,以供ParameterNamesModule使用。它减少了某些注释。

# 安全
出于安全原因,不允许将Jackson序列化程序绑定到开放式类型,可能是序列化小工具的目标对象,例如:

- java.lang.Object
- java.io.Serializable
- java.util.Comparable。

Jackson数据绑定定义的可能序列化小工具类的拒绝列表,需要检查并禁止反序列化。

>警告
不要使用@JsonTypeInfo(use = Id.CLASS)或ObjectMapper.enableDefaultTyping,因为使用多态类型会带来安全隐患。

##格式
支持以下格式,如上所述,您选择在序列化绑定配置中使用哪种格式。

- jackson-json-基于普通文本的JSON
- jackson-cbor-二进制CBOR数据格式

二进制格式比JSON格式更紧凑,性能稍好。

# 注解
## 单参数构造函数
您可能会遇到如下异常:

MismatchedInputException:无法构造...的实例(尽管存在至少一个Creator):无法从Object值反序列化(没有基于委托或基于属性的Creator)


这可能是因为该类的构造函数带有单个参数,例如:
可以通过添加@JsonCreator或@JsonProperty注解来解决:

或者

如Jackson文档中所述,使用JsonCreator.Mode.PROPERTIES配置ParameterNamesModule。

## 多态类型
多态类型是某个基本类型具有多个替代实现的情况。 如果嵌套字段或集合是多态类型,则必须使用@JsonTypeInfo和@JsonSubTypes注解列出该类型的具体实现。

例:

如果您尚未定义注释,则会看到如下异常:

InvalidDefinitionException:无法构造...的实例(不存在任何创建者,如默认构造一样):抽象类型需要映射到具体类型,具有自定义反序列化器或包含其他类型信息


请注意,对于顶级类,这不是必需的,但对于其中的字段,则需要。在此示例中,在动物园内部使用动物,该动物作为消息发送或保留。如果动物是独立发送或持久保存的,则不需要注释,因为被序列化的是具体的子类Lion或Elephant。

在使用这些注解指定允许的子类时,类名将不包括在序列化表示中,这对于防止反序列化时加载恶意序列化小工具很重要。

>警告
不要使用@JsonTypeInfo(use=Id.CLASS)或ObjectMapper.enableDefaultTyping,因为使用多态类型会带来安全隐患。

# 架构演变
在使用事件溯源以及进行滚动更新时,架构演变成为开发应用程序的重要方面。需求以及我们对业务领域的理解可能会(并且将会)随时间而变化。

Jackson序列化器提供了一种在反序列化期间执行JSON树模型转换的方法。对于文本格式和二进制格式,它以相同的方式工作。

我们将研究几种有关类如何演变的方案。

## 移除字段
无需迁移任何代码即可删除字段。 Jackson序列化程序将忽略该类中不存在的属性。

## 新增字段
无需迁移任何代码即可添加可选字段。默认值为Optional.empty。

旧类:
具有新的可选Discount属性和具有默认值的note字段的新类:

假设我们要拥有一个没有默认值的必填字段discount:

要添加新的必填字段,我们必须使用JacksonMigration类并在迁移代码中设置默认值。

这是添加discount字段的迁移类的样子:

覆盖currentVersion方法以定义当前(最新)版本的版本号。 当不使用任何迁移时,第一个版本始终为1。只要执行不带迁移代码就无法向后兼容的更改,请增加此版本号。

使用transform方法将旧的JSON结构转换为新的JSON结构。 JsonNode是可变的,因此您可以添加和删除字段,或更改值。 请注意,您必须转换为特定的子类,例如ObjectNode和ArrayNode才能访问更改器。

迁移类必须在配置文件中定义:
note字段可能也做同样的事情,在ItemAddedMigration中添加默认值“”。

## 重命名字段
假设我们要在上一个示例中将productId字段重命名为itemId。

迁移代码如下:

## 结构变化
以类似的方式,我们可以进行任意的结构更改。

旧类:
新类
Address 类
迁移代码如下:

## 重命名类
也可以重命名该类。 例如,让我们将OrderAdded重命名为OrderPlaced。

旧类:
新类
迁移代码如下:

请注意,重写transformClassName方法,定义新的类名称。

必须使用旧的类名作为键来配置这种类型的迁移。可以删除实际的类。
## 从序列化绑定中删除
当某个类不再用于序列化时,可以将其从序列化绑定中删除,但仍要允许反序列化,则必须在allowed-class-prefix配置中列出该类。例如,在通过序列化更改进行滚动更新期间,或在读取旧的存储数据时,此功能很有用。从Jackson序列化程序更改为另一个序列化程序(例如Protobuf)从而更改序列化绑定时,也可以使用它,但是仍然可以使用Jackson来反序列化旧数据。
这是类名称或类名称前缀的列表。

# Jackson模块
默认情况下,以下Jackson模块是启用的:

您可以修改配置akka.serialization.jackson.jackson-modules以启用其他模块。

ParameterNamesModule要求启用-parameters Java编译器选项。

## 压缩
JSON可能很冗长,对于大型消息,压缩大型有效负载可能会有所帮助。 对于jackson-json绑定,默认配置为:

支持的压缩算法为:gzip,lz4。使用“关闭”禁用压缩。 Gzip通常比lz4慢。大于compress-larger-than属性的消息将被压缩。

可以通过将算法属性设置为关闭来禁用压缩。它仍然能够解压缩序列化时压缩的有效载荷,例如如果更改此配置。

对于杰克逊cbor和自定义绑定,默认情况下禁用杰克逊json压缩,但可以采用与上述配置相同的方式启用,但用绑定名称替换杰克逊json(例如杰克逊cbor)。

附加配置
每个绑定的配置
默认情况下,在akka.serialization.jackson部分中定义了Jackson序列化程序及其ObjectMappers的配置。可以在更特定的akka​​.serialization.jackson。部分中覆盖该配置。

akka.serialization.jackson.jackson-json {
  序列化功能{
    WRITE_DATES_AS_TIMESTAMPS =关闭
  }
}
akka.serialization.jackson.jackson-cbor {
  序列化功能{
    WRITE_DATES_AS_TIMESTAMPS =开启
  }
}
也可以定义多个绑定并为它们使用不同的配置。例如,远程消息和持久事件的不同设置。

你可能感兴趣的:(akka,cluster)