-
-
Notifications
You must be signed in to change notification settings - Fork 229
Deserialization of Xml with @JacksonXmlText
, java.util.Map
fails
#615
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Thank you @kistlers. Yes, a new issue with reproduction works. I labelled it with |
I think the At least, I still got the same error using these two final classes (IntelliJ -> convert to record, the make sure they correspond to the same records as above) when I remove the
However, this works (no final classes and fields, all public properties, no setters/getters). I also quickly tested that with private fields with getters and setters, which also works:
|
@kistlers Thank you. I was about to suggest trying to see if equivalent POJO exhibited same problem. I suspect this may be due to more general |
Another note: use of But I am also confused as to intent of 2 annotated constructrors:
both of which would be detected; but that cannot really be used together (how would Jackson know which one to use, basically). I guess it'd be good to have still bit more minimal reproduction as I am not quite sure how this model is expected to work, esp. wrt |
About the use of the Anyway, here is a simpler reproduction (I think). I removed the outer So this fails: class XmlMapperReproductionTest {
@Test
void testDeserializeItemRoot() throws JsonProcessingException {
var xmlMapper = new XmlMapper().registerModule(new ParanamerModule());
var item = new Item("name1", "value1");
var itemSerialized = xmlMapper.writerWithDefaultPrettyPrinter().writeValueAsString(item);
var itemXml = """
<Item name="name1">value1</Item>
""";
assertEquals(itemXml, itemSerialized);
var itemDeserialized = xmlMapper.readValue(itemXml, Item.class);
assertEquals(item, itemDeserialized);
}
@JacksonXmlRootElement
public record Item(
@JsonProperty("name") @JacksonXmlProperty(isAttribute = true) String name,
@JacksonXmlText String value) {}
} with the error message: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Invalid definition for property '' (of type `ch.ubique.backend.test.assertion.XmlMapperReproductionTest$Item`): Could not find creator property with name '' (known Creator properties: [name, value])
at [Source: (StringReader); line: 1, column: 1] Swapping the record to this very simple POJO (the Equals, HashCode, and constructor are only there to keep the Test class identical): @JacksonXmlRootElement
public static class Item {
@JsonProperty("name")
@JacksonXmlProperty(isAttribute = true)
public String name;
@JacksonXmlText public String value;
public Item(String name, String value) {
this.name = name;
this.value = value;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof Item item)) {
return false;
}
return new EqualsBuilder().append(name, item.name).append(value, item.value).isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder(17, 37).append(name).append(value).toHashCode();
}
} Also, using this @JacksonXmlRootElement
public static class Item {
@JsonProperty("name")
@JacksonXmlProperty(isAttribute = true)
private final String name;
@JacksonXmlText private final String value;
public Item(String name, String value) {
this.name = name;
this.value = value;
}
public String getName() {
return name;
}
public String getValue() {
return value;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof Item item)) {
return false;
}
return new EqualsBuilder().append(name, item.name).append(value, item.value).isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder(17, 37).append(name).append(value).toHashCode();
}
} |
Simple workaround is to add @JacksonXmlProperty(localName = "") along with @JacksonXmlText. Could be done in meta-annotation too. @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@JacksonXmlText
@JacksonXmlProperty(localName = "")
@JacksonAnnotationsInside
public @interface XmlText {
} |
@Aemmie Your meta-annotation solution wraps value into another xml element. It's not text. And use of |
I just ran into this issue in version 2.18.1. I notice the label says 2.17, any plans to look at the issue? |
@Lorkster I do not think anyone is actively working on this issue. Removed the label to avoid misunderstanding. |
@JacksonXmlText
fails@JacksonXmlText
, java.util.Map
fails
This even fails for me with the extra |
Right, EDIT: #306 is for the general problem. But this is bit more specific so leaving open for now. |
any progress on this? Swapped jaxb to jackson because it supported records but apparently not, makes the library useless for me |
@filip-krasinski If there was progress, there'd be note here. No note, no progress. |
Added |
I have a similar issue with deserialization. @Data
@SuperBuilder
@JacksonXmlRootElement(localName = "soap:Envelope")
public class Envelope {
@Builder.Default
@JacksonXmlProperty(isAttribute = true, localName = "xmlns:soap")
private String soap = "http://schemas.xmlsoap.org/soap/envelope/";
@Builder.Default
@JacksonXmlProperty(isAttribute = true, localName = "xmlns:xsd")
private String xsd = "http://www.w3.org/2001/XMLSchema";
@Builder.Default
@JacksonXmlProperty(isAttribute = true, localName = "xmlns:xsi")
private String xsi = "http://www.w3.org/2001/XMLSchema-instance";
}
@Data
@SuperBuilder
@EqualsAndHashCode(callSuper = true)
public class ValidateFilingEnvelope extends Envelope {
@JacksonXmlProperty(localName = "soap:Body")
private ValidateFilingBody body;
}
@Data
@Builder
public class ValidateFilingBody {
@JacksonXmlProperty(localName = "ValidateFilingResponse")
private ValidateFilingResponse validateFilingResponse;
}
@Data
@Builder
public class ValidateFilingResponse {
@Builder.Default
@JacksonXmlProperty(isAttribute = true)
private String xmlns = "https://www.test.com/";
@JacksonXmlProperty(localName = "ValidateFilingResult")
private ValidateFilingResult validateFilingResult;
}
@Data
@Builder
public class ValidateFilingResult {
@Builder.Default
@JacksonXmlElementWrapper(localName = "Messages")
@JacksonXmlProperty(localName = "Message")
private List<Message> messages = new ArrayList<>();
}
@Data
@Builder
public class Message {
@JacksonXmlProperty(isAttribute = true)
private String level;
@JacksonXmlText
private String content;
} I am able to serialize the class object into an xml var e3 = ValidateFilingEnvelope.builder()
.body(
ValidateFilingBody.builder()
.validateFilingResponse(
ValidateFilingResponse.builder()
.validateFilingResult(
ValidateFilingResult.builder()
.messages(List.of(
Message.builder().level("0").content("Filing passed with no validation errors.").build()
))
.build()
)
.build()
)
.build()
)
.build();
log.info(xmlMapper.writeValueAsString(e3)); output formatted <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Body>
<ValidateFilingResponse xmlns="https://www.test.com/">
<ValidateFilingResult>
<Messages>
<Message level="0">Filing passed with no validation errors.</Message>
</Messages>
</ValidateFilingResult>
</ValidateFilingResponse>
</soap:Body>
</soap:Envelope> But when I try to deserialize the xml back to the java class var text = """
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Body>
<ValidateFilingResponse xmlns="https://www.test.com/">
<ValidateFilingResult>
<Messages>
<Message level="0">Filing passed with no validation errors.</Message>
</Messages>
</ValidateFilingResult>
</ValidateFilingResponse>
</soap:Body>
</soap:Envelope>""";
var envelope = xmlMapper.readValue(text, ValidateFilingEnvelope.class);
log.info(envelope); I got the following error
|
This is a reproduction of #198. It was mentioned opening a new issue is preferred.
The issue is, that
@JacksonXmlText
seems to work as intended for serialization, but not for deserialization.Hence, my reproduction of the original issue with 2.15.4:
I have the following models and tests:
First, I serialize the model to verify what I actually want to deserialize is correct and then I serialize the XML again.
The tests pass because of
@JsonCreator
inItem
. Without the annotation, I get the following error on thexmlMapper.readValue()
:The text was updated successfully, but these errors were encountered: