jackson-dataformat-xml icon indicating copy to clipboard operation
jackson-dataformat-xml copied to clipboard

Can not use `@JacksonXmlText` for Creator property (creator parameter)

Open ewirch opened this issue 5 years ago • 3 comments

(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.

ewirch avatar Aug 30 '18 06:08 ewirch

I'm running into this too. Does anyone have a sensible workaround?

edziegle avatar Sep 01 '18 16:09 edziegle

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.

cowtowncoder avatar May 23 '20 03:05 cowtowncoder

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

Chesterdam avatar Jan 13 '21 11:01 Chesterdam