【发布时间】:2020-02-07 05:52:21
【问题描述】:
我正在尝试实现HL7 FHIR spec's assertion that JSON representing a FHIR model will not have empty objects nor empty arrays。为了不让我的消费者的生活更加困难,我没有在反序列化期间严格执行这一点,但我想确保我的库生成的序列化 JSON 符合指定的要求。我正在使用 Java 和 Jackson ObjectMapper 将对象序列化为 JSON。我对编写自定义序列化程序的理解是,无论您要转换为什么,Object 在某一时刻都表示为 JsonNode。
我想做的是在 JsonNode 退出序列化程序时拦截它,对其进行一些调整(查找并删除空数组和对象),然后让它继续前进。我需要在无法调整 ObjectMapper 的环境中执行此操作,因为我无权访问它。此外,该库中模型的复杂层次结构大量使用 Jackson 的默认序列化和注释等,我无法消除这一点。
如果我为基本类型定义自定义序列化程序,比如说“资源”,那么我就有问题了,因为我仍然需要原始序列化程序的输出来生成我修改后的输出。此外,这需要适应模型中各种类型可能已经存在的任何自定义序列化程序。
我在使用https://www.baeldung.com/jackson-call-default-serializer-from-custom-serializer 和最后一个选项实现 BeanSerializerModifier 的情况下取得了相当大的进展,但我遇到了无法控制我的库消费者使用的 ObjectMapper 的问题。
示例 POJO(使用 Lombok 作为访问器):
@Data
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@JsonIgnoreProperties(ignoreUnknown = true)
abstract class Resource {
private FhirString id;
private List<Extension> extension;
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
public abstract ResourceType getResourceType();
}
@Data
@Builder
class SomethingElse extends Resource {
FhirUri someProperty;
CodeableConcept someCode;
List<Reference> someReferences;
@Override
public ResourceType getResourceType() {
return ResourceType.SOMETHING_ELSE;
}
}
还有一个 SomethingElse 类的示例实例:
SomethingElse somethingElse = SomethingElse.builder()
.someProperty(FhirUri.from("some-simple-uri"))
.someCode(new CodeableConcept())
.someReference(List.of(new Reference()))
.build();
somethingElse.setId(FhirString.randomUuid());
somethingElse.setExtension(new ArrayList<>());
当我告诉任何映射器(或者,例如,使用 Spring 服务)将 SomethingElse 类映射到 JsonNode 时,例如,我可以得到空对象和数组,如下所示:
ObjectMapper mapper = getUntouchableMapper();
JsonNode somethingElseNode = mapper.valueToTree(somethingElse);
System.out.println(somethingElseNode.toString());
变成:
{
"resourceType": "SomethingElse",
"id": "00000000-0002-0004-0000-000000000000",
"someProperty": "some-simple-uri",
"someCode": {},
"someReferences": [{}],
"extension": []
}
根据 FHIR,这实际上应该如下所示:
{
"resourceType": "SomethingElse",
"id": "00000000-0002-0004-0000-000000000000",
"someProperty": "some-simple-uri"
}
总结
无论使用何种 ObjectMapper,我如何保留现有的序列化机制,并以某种方式从 Jackson 序列化过程生成的传出 JSON 中删除空列表和对象?
编辑:
我还尝试了@JsonInclude(JsonInclude.Include.NON_EMPTY),它确实省略了空列表实现。但是,这个库中的绝大多数数据都是由序列化为映射和图元的 POJO 表示的,并且只有当它们直接由模型中的映射和图元表示时,此注解才有效。
【问题讨论】:
-
@JsonSerialize(include = Inclusion.NON_EMPTY)? -
@dai
JsonSerialize.Inclusion已弃用,但将其现代等效项@JsonInclude(JsonInclude.Include.NON_EMPTY)放在我的模型上仅适用于地图、列表和 srting,不适用于序列化为地图、列表或字符串的对象.它在序列化中过早地执行检查。我将在原始问题中对此进行说明。 -
这确实揭示了NON_EMPTY 文档中提到的一些内容,这使我得到了这个答案,这可能会使注释起作用:stackoverflow.com/a/31034525/1708977 不幸的是,这也需要我修改映射器,我无法访问。
标签: java json jackson hl7-fhir