如何使用列表名称的自定义名称(反)序列化不可变对象?
How to (de)serialize immutable object with custom name for list name?
我正在尝试使用 Jackson 将对象序列化和反序列化为 XML,但是我很难这样做...
我的对象:
- 是一个不可变的 class,只有 getter 和构造函数
- 它包含一个子对象消息列表
- 我想序列化这个包含在元素
<messages>
中的列表,并将每条消息作为一个 <message>
元素 - 据我所知,我必须在 getter 上放置 @JsonProperty("message") @JacksonXmlElementWrapper(localName = "messages")
注释,因为当我将它放在构造函数上,它不会产生所需的输出(两者相同<message(s)>
)
<response id="response-id">
<messages>
<message code="a"/>
<message code="b"/>
</messages>
</response>
- 我需要反序列化这个结构,但是由于它是具有最终变量的不可变对象,我必须通过构造函数反序列化它。
代码片段:
public class Playground {
public static void main(String[] args) throws JsonProcessingException {
Response response = new Response("response-id", List.of(new Message("a"), new Message("b")));
XmlMapper xmlObjectMapper = new XmlMapper(new XmlFactory());
xmlObjectMapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
final String value = xmlObjectMapper.writeValueAsString(response);
System.out.println(value);
assert ("<response id=\"response-id\"><messages><message code=\"a\"/><message "
+ "code=\"b\"/></messages></response>")
.equals(value) : "Desired format does not match!";
final Response deserializedValue = xmlObjectMapper.readValue(value, Response.class);
//final String deserialized = xmlObjectMapper.writeValueAsString(deserializedValue);
//assert value.equals(deserialized) : "Does not match";
}
}
@JsonInclude(Include.NON_EMPTY)
@JacksonXmlRootElement(localName = "response")
@JsonPropertyOrder({"id", "messages"})
class Response {
private final String id;
private final List<Message> messages;
@JsonCreator
public Response(
@JacksonXmlProperty(localName = "id", isAttribute = true) final String id,
@JsonProperty("message") final List<Message> messages) {
this.id = id;
this.messages = messages;
}
@JacksonXmlProperty(localName = "id", isAttribute = true)
public String getId() {
return id;
}
@JsonProperty("message")
@JacksonXmlElementWrapper(localName = "messages")
public List<Message> getMessages() {
return messages;
}
}
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(Include.NON_EMPTY)
class Message {
private final String code;
public Message(@JacksonXmlProperty(localName = "code", isAttribute = true) final String code) {
this.code = code;
}
@JacksonXmlProperty(localName = "code", isAttribute = true)
public String getCode() {
return code;
}
}
- 当我在构造函数中没有注释
messages
的情况下尝试反序列化时,出现异常:Invalid type definition for type 'Response': Argument #1 of constructor [constructor for 'Response' (2 args), annotations: {interface JsonCreator=@JsonCreator(mode=DEFAULT)} has no property name (and is not Injectable): can not use as property-based Creator
- 当我添加
@JsonProperty("message")
注释时,出现异常:Invalid definition for property 'messages' (of type 'Response'): Could not find creator property with name 'messages' (known Creator properties: [id, message])
- 当我将其更改为
@JsonProperty("messages")
(复数)时,我得到:Duplicate property 'messages' for [simple type, class Response]
- 当我添加两者时,
@JsonProperty("message") @JacksonXmlElementWrapper(localName = "messages")
,它会产生异常:Invalid definition for property 'messages' (of type 'Response'): Could not find creator property with name 'messages' (known Creator properties: [id, message])
。 (这两个注释中 message/messages 的任何组合都不起作用)
我做错了什么?我需要使用哪些注释来检索所需的 XML 反序列化输出?
对于未来的 google 员工:
这似乎与 jackson-dataformat-xml 问题有关:
https://github.com/FasterXML/jackson-dataformat-xml/issues/187
还发布了解释和解决方法。
我正在尝试使用 Jackson 将对象序列化和反序列化为 XML,但是我很难这样做...
我的对象:
- 是一个不可变的 class,只有 getter 和构造函数
- 它包含一个子对象消息列表
- 我想序列化这个包含在元素
<messages>
中的列表,并将每条消息作为一个<message>
元素 - 据我所知,我必须在 getter 上放置@JsonProperty("message") @JacksonXmlElementWrapper(localName = "messages")
注释,因为当我将它放在构造函数上,它不会产生所需的输出(两者相同<message(s)>
)
<response id="response-id">
<messages>
<message code="a"/>
<message code="b"/>
</messages>
</response>
- 我需要反序列化这个结构,但是由于它是具有最终变量的不可变对象,我必须通过构造函数反序列化它。
代码片段:
public class Playground {
public static void main(String[] args) throws JsonProcessingException {
Response response = new Response("response-id", List.of(new Message("a"), new Message("b")));
XmlMapper xmlObjectMapper = new XmlMapper(new XmlFactory());
xmlObjectMapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
final String value = xmlObjectMapper.writeValueAsString(response);
System.out.println(value);
assert ("<response id=\"response-id\"><messages><message code=\"a\"/><message "
+ "code=\"b\"/></messages></response>")
.equals(value) : "Desired format does not match!";
final Response deserializedValue = xmlObjectMapper.readValue(value, Response.class);
//final String deserialized = xmlObjectMapper.writeValueAsString(deserializedValue);
//assert value.equals(deserialized) : "Does not match";
}
}
@JsonInclude(Include.NON_EMPTY)
@JacksonXmlRootElement(localName = "response")
@JsonPropertyOrder({"id", "messages"})
class Response {
private final String id;
private final List<Message> messages;
@JsonCreator
public Response(
@JacksonXmlProperty(localName = "id", isAttribute = true) final String id,
@JsonProperty("message") final List<Message> messages) {
this.id = id;
this.messages = messages;
}
@JacksonXmlProperty(localName = "id", isAttribute = true)
public String getId() {
return id;
}
@JsonProperty("message")
@JacksonXmlElementWrapper(localName = "messages")
public List<Message> getMessages() {
return messages;
}
}
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(Include.NON_EMPTY)
class Message {
private final String code;
public Message(@JacksonXmlProperty(localName = "code", isAttribute = true) final String code) {
this.code = code;
}
@JacksonXmlProperty(localName = "code", isAttribute = true)
public String getCode() {
return code;
}
}
- 当我在构造函数中没有注释
messages
的情况下尝试反序列化时,出现异常:Invalid type definition for type 'Response': Argument #1 of constructor [constructor for 'Response' (2 args), annotations: {interface JsonCreator=@JsonCreator(mode=DEFAULT)} has no property name (and is not Injectable): can not use as property-based Creator
- 当我添加
@JsonProperty("message")
注释时,出现异常:Invalid definition for property 'messages' (of type 'Response'): Could not find creator property with name 'messages' (known Creator properties: [id, message])
- 当我将其更改为
@JsonProperty("messages")
(复数)时,我得到:Duplicate property 'messages' for [simple type, class Response]
- 当我添加两者时,
@JsonProperty("message") @JacksonXmlElementWrapper(localName = "messages")
,它会产生异常:Invalid definition for property 'messages' (of type 'Response'): Could not find creator property with name 'messages' (known Creator properties: [id, message])
。 (这两个注释中 message/messages 的任何组合都不起作用)
我做错了什么?我需要使用哪些注释来检索所需的 XML 反序列化输出?
对于未来的 google 员工:
这似乎与 jackson-dataformat-xml 问题有关: https://github.com/FasterXML/jackson-dataformat-xml/issues/187
还发布了解释和解决方法。