我们正在构建一个应用程序,它可能会从我们的简化对象模型中生成数百个唯一的JSON有效负载结构,我们希望避免向Java代码库中添加数百个POJO(每个唯一的有效负载结构一个)。
我们构建了一种方法来构建、解析负载结构的简单字符串规范,并将其覆盖到POJO中,然后遍历其树以匹配任何@JsonProperty
字段。
String spec = """
firstName
lastName
addresses.line1
addresses.city
children.firstName
children.schedule.bedtime
"""
这将在运行时覆盖在Person
POJO上,它将遍历并获取指定的字段和数组。尽管Person
、Child
和Address
POJO中有很多字段,但此特定消息请求应仅填充我们指定的字段。此请求的JSON输出应为:
{
"firstName": "Mickey",
"lastName": "Mouse",
"addresses": [
{
"line1": "123 Disneyland Way",
"city": "Anaheim"
},
{
"line2": "345 Disneyworld Drive",
"city": "Orlando"
}
],
"children": [
"firstName": "Junior",
"schedule": [
"bedtime": "20:00"
]
]
}
- 请原谅我...似乎只有一个迪士尼角色有孩子(Ariel)*
目前,我们只测试了我们的Spec和POJO的遍历,以找到Spec的适用之处,但是我们还不能弄清楚如何将其连接到JSON序列化过程中。
我所读到的关于Jackson/JSON/Spring序列化器和反序列化器的所有内容似乎都只接受1个输入--POJO。有没有办法使用使用2个输入(POJO + Spec)的自定义序列化器,其中Spec在运行时被标识(从而消除了为每个Spec创建一个“ Package 器”POJO和/或序列化器的需要)?
为了使事情变得更有挑战性,我们希望简化我们的@RestController
方法,以简单地包括我们的新注解@APIMessageSpec(<details go here>)
以及@ResponseBody
注解,然后让Spring调用我们的自定义序列化过程,传入POJO和我们的@APIMessageSpec
的细节(或者我们可以将@ResponseBody
子类化,以参数化其参数中的Spec信息,这样我们就不需要2个注解了)。
提前感谢!Michael
1条答案
按热度按时间bjp0bcyl1#
我想出了一个解决办法后不久,张贴这一点!
我们所有的数据/对象模型POJO在它们的祖先中共享一个超类
BaseModelEntity
(我们在其中放置了一些公共字段,如UUID、上次更新用户/时间戳等)。我们为自定义序列化规则创建了
ModelJsonSerializer extends JsonSerializer<BaseModelEntity>
。我们挑选了一个带有
@Autowired ObjectMapper objectMapper
的bean来添加以下方法:我们有一个静态的
APISpecRegistry
类,我们在其中将所有的规范[它们都是我们自定义的APISpec
超类的子类]加载到一个HashMap中。在
@RestController
的方法上,或者在应用程序中的任何地方,我们用@JsonView(<our_Spec_class>)
注解返回类型。当Jackson识别并开始处理我们的任何数据模型对象时,它成功地找到了
ModelJsonSerializer
作为我们的数据类型BaseModelEntity
的正确对象。在
ModelJsonSerializer
中,我们有以下方法:注意:
APISpec.getFields()
是我们将规范从字符串格式解析为要遍历的POJO字段层次结构的地方。我们通过
serializers.getActiveView()
获取当前的@JsonView
,从该视图中获取APISpec
类,并将其用作从APISpecRegistry
中查找APISpec
对象的键然后,在我们的自定义4参数
serialize
方法中,我们将每个字段的API规则与BaseModelEntity
示例中的相应字段值进行交叉引用,并忽略不在我们的规范中的任何BaseModelEntity
字段。提示:在底层,我们使用Java反射找到
java.lang.reflect.Field
,它带有@JsonProperty
注解,与APISpec
中的字段匹配。太神奇了!