java - 使用 Jackson 序列化 XML“选择”元素
问题描述
我们有一个这种形式的 XSD:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified" version="1.0.0">
<xs:element name="SomeEndpoint">
<xs:complexType>
<xs:choice>
<xs:element name="RequestPayload">
<!-- snip -->
</xs:element>
<xs:element name="ResponsePayload">
<!-- snip -->
</xs:element>
<xs:element name="ErrorPayload">
<!-- snip -->
</xs:element>
<xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
没关系,如果我们喜欢它;它给了。例如,对于一个请求,我们会得到表单的 XML
<SomeEndpoint>
<RequestPayload>
<!-- snip -->
</RequestPayload>
</SomeEndpoint>
为了我们自己的理智,我们想要三个 POXO,可以这么说:
@JsonTypeName("RequestPayload")
class SomeEndpointRequestPayload {
}
@JsonTypeName("ResponsePayload")
class SomeEndpointResponsePayload {
}
@JsonTypeName("ErrorPayload")
class SomeEndpointErrorPayload {
}
到目前为止,一切都很好——我们可以使用带有 的 Jackon 2.11.0jackson-dataformat-xml:2.11.2
序列化“真实”对象就好了。FWIW,我们使用如下配置的映射器:
public XmlMapper payloadMapper() {
var xmlMapper = new XmlMapper();
xmlMapper.registerModule(new JavaTimeModule());
xmlMapper.registerModule(new JaxbAnnotationModule());
return xmlMapper;
}
现在我们“只”需要那个包装标签,SomeEndpoint
. 我们尝试过的事情:
根路径:我们认为可以通过
@JsonRootName
或为 POXO 注入自定义“根路径”@JacksonXmlRootElement
。我们尝试传递名称,例如SomeEndpoint.RequestPayload
orSomeEndpoint/RequestPayload
; 没运气。Wrapper Object:这似乎是最自然的解决方案,但我们很难获得以该属性命名的额外包装标签。特别是,杰克逊不接受这种变体:
@JsonRootName(value = "SomeEndpoint") class SomeEndpointWrapper { @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT) @JsonUnwrapped Object payload; }
这个仍然输出一个
<payload>
标签:@JsonRootName(value = "SomeEndpoint") class SomeEndpointWrapper { @XmlElements({ @XmlElement(name="RequestPayload", type=SomeEndpointRequestPayload.class), @XmlElement(name="ResponsePayload", type=SomeEndpointResponsePayload.class), @XmlElement(name="ErrorPayload", type=SomeEndpointErrorPayload.class) }) Object payload; }
我们已经尝试了太多的注释组合来计算或在这里复制,但这两个似乎“应该工作”。
注意:我们一直在使用标记界面,而不是
Object
将值限制为三种类型。由于它似乎对杰克逊没有什么影响,为了简单起见,我把它省略了。解决方法:我们可以为每个选项选择一个属性:
@Data @JsonRootName(value = "SomeEndpoint") class SomeEndpointWrapper { @JsonProperty(value = "Request") private SomeEndpointRequestPayload request; @JsonProperty(value = "Antwort") private SomeEndpointResponsePayload successResponse; @JsonProperty(value = "Fehlerinformation") private SomeEndpointErrorPayload errorResponse; }
这行得通,但是……不,真的吗?
choice
在 POXO中实现 XML 而不创建虚假包装标签的好方法是什么?
解决方案
推荐阅读
- python - 如何在 sqlalchemy 中管理多个数据库和一个模型
- php - Laravel:stream_socket_enable_crypto():SSL 操作失败,代码为 1
- java - 将 XML 解析为 Java 对象节点
- php - 目录中的文件不按顺序
- python - 有效计算给定开始/结束时间之间的 IntervalVars
- arrays - 根据来自另一个数组 Swift 的顺序对数组进行排序
- r - 如何在带有警告的 for 循环中绘制多个图?
- swift - 如何使用 Swift 将一对字节转换为浮点数
- matlab - 在 Matlab 中嵌套多个函数
- stormcrawler - Stromcrawler 1.16 中的构建失败