我将域类对象转换为JSON格式,将它们存储到文档数据库中。在存储之前,我希望对特定自定义类型LocalizedTexts
的所有属性应用转换,并将它们作为条目存储到平面List/Array
中。
为了更好地理解需求,下面是一些基本类:
这是主域类:
@Value
@NoArgsConstructor(force = true, access = AccessLevel.PRIVATE)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@SuperBuilder(toBuilder = true)
@JsonDeserialize(builder = Article.ArticleBuilderImpl.class)
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class Article extends AbstractEntityBase {
@NonNull
UUID id;
@JsonProperty("iNo")
Integer iNo;
boolean isValid;
@NonNull
LocalizedTexts designation;
@NonNull
ReferenceArticleGroup articleGroup;
Integer numberOfDecimalsSalesPrice;
LocalizedTexts touchCaption;
LocalizedTexts printText;
LocalizedTexts productInformation;
@Singular
List<String> codes;
...
}
这是内部LocalizedTexts类:
@Builder(builderMethodName = "internalBuilder")
public class LocalizedTexts extends HashMap<Language, String> implements EntityBase {
public LocalizedTexts() {
}
public LocalizedTexts(Map map) {
putAll(map);
}
}
最后,Language
枚举类型:
public enum Language {
AA("aa"),
AB("ab"),
AE("ae"),
AF("af"),
AK("ak"),
...
}
请注意Language
和LocalizedTexts
是从另一个库导入的,因此我没有更改它们的权限。
标准Jackson对象Map器生成一个JSON文件,其结构如下:
{
"id": "57bf6daf-4993-4c55-9b19-db6b3d5c9527",
"iNo": 3,
"isValid": true,
"designation": {
"de": "designation3DE localized designation3 designation",
"en": "designation3EN localized designation3 designation"
},
"articleGroup": {
"id": "8f6627b8-31d4-4e44-9374-6069571489f7",
"type": "ArticleGroup"
},
"numberOfDecimalsSalesPrice": 2,
"touchCaption": {
"de": "touchCaption3DE localized touchCaption3 touchCaption",
"en": "touchCaption3EN localized touchCaption3 touchCaption"
},
"printText": {
"de": "printText3DE localized printText3 printText",
"en": "printText3EN localized printText3 printText"
},
"productInformation": {
"de": "productInformation3DE localized productInformation3 productInformation",
"en": "productInformation3EN localized productInformation3 productInformation",
"es": "productInformation3ES localized productInformation3 productInformation"
},
"codes": [
"1231231231234",
"2345678901234",
"9999999999999",
"1111111111111"
],
...
}
我想把我的对象序列化成一个json,格式如下:
{
"id": "57bf6daf-4993-4c55-9b19-db6b3d5c9527",
"iNo": 3,
"isValid": true,
"articleGroup": {
"id": "8f6627b8-31d4-4e44-9374-6069571489f7",
"type": "ArticleGroup"
},
"numberOfDecimalsSalesPrice": 2,
"codes": [
"1231231231234",
"2345678901234",
"9999999999999",
"1111111111111"
],
"translation": [
{
"productInformation": "productInformation3DE localized productInformation3 productInformation",
"language": "german"
},
{
"productInformation": "productInformation3EN localized productInformation3 productInformation",
"language": "english"
},
{
"productInformation": "productInformation3ES localized productInformation3 productInformation",
"language": "spanish"
},
{
"touchCaption": "touchCaption3DE localized touchCaption3 touchCaption Bildbeschriftung",
"language": "german"
},
{
"touchCaption": "touchCaption3EN localized touchCaption3 touchCaption Caption",
"language": "english"
},
{
"designation": "designation3DE localized designation3 designation",
"language": "german"
},
{
"designation": "designation3EN localized designation3 designation",
"language": "english"
}
],
...
}
型
所以我想提取所有的LocalizedTexts条目对,并将它们添加到一个数组中,如上所示。当从数据库阅读回时,我想实现相反的转换,并将上面的JSON反序列化到我原来的域类中。
我想我应该实现一个自定义的序列化器/反序列化器,并将其注册到我的ObjectMapper
for 'Article'类(如此处所述)和here中。
据我所知,我应该使用反思的目的,但也许这将是一个矫枉过正。任何其他的想法或建议?
1条答案
按热度按时间np8igboo1#
我想我应该实现一个自定义的序列化器/反序列化器
当然,可以通过扩展抽象类
StdSerializer
并提供其serialize()
方法的实现来实现自定义Serializer,但这需要大量底层代码,而且不灵活。另一种选择是为
Article
类型创建一个所谓的Converter
,并通过@JsonSerialize
注解的converter
属性提供它。以下是解释Converter用途的文档中的一段引文:使用哪个帮助对象将类型转换为Jackson知道如何序列化的对象;这可能是因为基类型无法轻松序列化,也可能只是为了更改序列化。
换句话说,Converter的目标是将基本类型转换为另一种更容易序列化的类型。而Serializer的目的是通过
JsonGenerator
指示Jackson如何从给定的对象生成JSON(* 这在复杂的对象图中不是很方便,需要做很多更改 *)。这就是你如何区分两者的方法。要为
Article
类型创建自定义Converter,我们需要扩展抽象类StdConverter
并覆盖其convert()
方法,期望Article
的示例并返回一个不同的对象,该对象可以顺利地反序列化。因此,首先,让我们创建此类型,用于存储根据需要构建的LocalizedTexts
类型字段中的数据。我们把这个类型叫做
ArticleWrapper
:它还需要一个名为
LanguageAttribute
的自定义类型来表示"{ "productInformation":"...", "language":"english" }"
之类的信息,我将其定义为Java 16record
(* 您也可以将其重新实现为普通的class
*):型
注意:
LanguageAttribute
有一个类型为 *Map
* 的字段。它是一个单条目Map,用于表示不同的属性,如 *"productInformation":"..."
、"designation":"..."
* 等。它被注解为 *@JsonAnyGetter
*,因为我们不希望属性 *"map"
* 出现在生成的JSON中(只需要它的内容)。另一个选项(有些人可能会觉得更直观)是 *@JsonUnwrapped
*,但它在这里不起作用,因为这个众所周知的documented issue在编写本文时仍然没有得到解析。下面是一个简单的转换器,它可以将
Language
枚举序列化为它的小写属性(***注意:**将用于访问小写语言名称的方法更改为正确的方法 *):最后,这里是
Article
类型的Converter实现,它稍微复杂一点,因为此Converter执行更多转换,但它是可维护的,可以根据需要进行更改/扩展:免责声明:
如果还需要定制反序列化的过程,我将把它留给OP/reader作为实践练习。