gpt4 book ai didi

java - Jackson:如何在序列化过程中对 JsonNode 进行后处理?

转载 作者:行者123 更新时间:2023-11-30 05:27:09 26 4
gpt4 key购买 nike

我正在尝试实现 HL7 FHIR spec's assertion that JSON representing a FHIR model will not have empty objects nor empty arrays 。为了不让我的消费者的生活变得更加困难,我在反序列化期间没有严格执行这一点,但我想确保我的库生成的序列化 JSON 符合指定的要求。我正在使用 Java 和 Jackson ObjectMapper 将对象序列化为 JSON。我对编写自定义序列化器的理解是,无论您要转换为什么,该对象在某一时刻都表示为 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 表示的,并且只有当它们直接由模型中的映射和基元表示时,此注释才有效。

最佳答案

解决方案是使用自定义的@JsonInclude,即new in Jackson 2.9 。感谢@dai 让我重新认识这个功能。

在资源基类上,如下所示:

@JsonInclude(value = JsonInclude.Include.CUSTOM, valueFilter = FhirJsonValueFilter.class)
class Resource implements FhirTypeInterface {
...

@Override
public boolean isEmpty() {
//Details omitted for simplicity
}
}

为了可见性,上面使用的界面:

interface FhirTypeInterface {
boolean isEmpty();
}

我对 FhirJsonValueFilter 的自定义定义实现了 JsonInclude.Include.NON_EMPTY 的所有功能,但还添加了用于检查 FHIR 类型实现的方法的功能(此实现与答案无关) )。

public class FhirJsonValueFilter {
@Override
public boolean equals(Object value) {
return !getWillInclude(value);
}

/**
* Returns true for an object that matched filter criteria (will be
* included) and false for those to omit from the response.
*/
public boolean getWillInclude(Object value) {
//Omit explicit null values
if (null == value) {
return false;
}

//Omit empty collections
if (Collection.class.isAssignableFrom(value.getClass())) {
return !((Collection) value).isEmpty();
}

//Omit empty maps
if (Map.class.isAssignableFrom(value.getClass())) {
return !((Map) value).isEmpty();
}

//Omit empty char sequences (Strings, etc.)
if (CharSequence.class.isAssignableFrom(value.getClass())) {
return ((CharSequence) value).length() > 0;
}

//Omit empty FHIR data represented by an object
if (FhirTypeInterface.class.isAssignableFrom(value.getClass())) {
return !((FhirTypeInterface) value).isEmpty();
}

//If we missed something, default to include it
return true;
}
}

请注意,自定义省略过滤器使用 Java 的 Object.equals 功能,其中 true 表示省略属性,并且我使用了第二种方法来减少此答案中的困惑。

关于java - Jackson:如何在序列化过程中对 JsonNode 进行后处理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58311830/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com