jackson-dataformat-xml
jackson-dataformat-xml copied to clipboard
Can not use `@JacksonXmlText` for Creator property (creator parameter)
(Refiling after wrong post in jackson-module-base #57)
See this test case:
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import com.fasterxml.jackson.dataformat.xml.JacksonXmlModule;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlText;
import org.junit.Test;
import java.beans.ConstructorProperties;
import java.io.IOException;
import javax.xml.bind.annotation.XmlAttribute;
public class JacksonXmlTextTest {
private static final String XML = "<ROOT><CHILD attr=\"attr_value\">text</CHILD></ROOT>";
@JacksonXmlRootElement(localName = "ROOT")
public static class Root {
@JacksonXmlProperty(localName = "CHILD") final Child child;
public Root(Child child) {
this.child = child;
}
public Child getChild() {
return child;
}
}
public static class Child {
@XmlAttribute
String attr;
@JacksonXmlText
String el;
public Child() {
}
@ConstructorProperties({"attr", "el"})
private Child(String attr, String el) {
this.attr = attr;
this.el = el;
}
public String getAttr() {
return this.attr;
}
public String getEl() {
return this.el;
}
public void setAttr(String attr) {
this.attr = attr;
}
public void setEl(String el) {
this.el = el;
}
}
@JacksonXmlRootElement(localName = "ROOT")
public static class RootWithoutConstructor {
@JacksonXmlProperty(localName = "CHILD") final ChildWithoutConstructor child;
@ConstructorProperties({"child"})
public RootWithoutConstructor(ChildWithoutConstructor child) {
this.child = child;
}
public ChildWithoutConstructor getChild() {
return child;
}
}
public static class ChildWithoutConstructor {
@XmlAttribute
String attr;
@JacksonXmlText
String el;
public String getAttr() {
return this.attr;
}
public String getEl() {
return this.el;
}
public void setAttr(String attr) {
this.attr = attr;
}
public void setEl(String el) {
this.el = el;
}
}
@Test
public void verifyJacksonXmlTextIsUnmarshalled() throws IOException {
final XmlMapper mapper = new XmlMapper(new JacksonXmlModule());
assertThat(
mapper.readValue(XML, Root.class).getChild().el,
is("text")
);
}
@Test
public void verifyJacksonXmlTextIsUnmarshalledWithoutConstructor() throws IOException {
final XmlMapper mapper = new XmlMapper(new JacksonXmlModule());
assertThat(
mapper.readValue(XML, RootWithoutConstructor.class).getChild().el,
is("text")
);
}
}
verifyJacksonXmlTextIsUnmarshalled() fails. verifyJacksonXmlTextIsUnmarshalledWithoutConstructor() succeeds.
I'm running into this too. Does anyone have a sensible workaround?
I can reproduce this, and I think I know what is the underlying issue: @XmlText annotated value has no real property name, and internally has nominal name of "" (empty String) as representation in token stream.
Unfortunately name "el" is specified with @ConstructorProperties so there is a mismatch.
Worse, the obvious fix -- changing name from "el" to "", to make it match -- does not work because in annotations "" is used as placeholder for "name not defined" (since annotations can not have null as default value), meaning that while it can be specified, it will not work and instead results in a different exception.
I hope to look into how to make renaming work properly in near future; added a failing test to help when I have time to do so.
I think I am also having this issue. I made a small project reproducing the problem relevant to my use case: https://github.com/Chesterdam/jackson_xml_problem