FasterXML / jackson-dataformat-xml

Extension for Jackson JSON processor that adds support for serializing POJOs as XML (and deserializing from XML) as an alternative to JSON
Apache License 2.0
565 stars 221 forks source link

@JacksonXmlElementWrapper Conflicting getter/setter definitions for property #27

Open n00bman opened 12 years ago

n00bman commented 12 years ago

Hi, I'm using latest release 2.0.1 and I've got a problem with serializing/deserializing xml (everything works fine in JSON). I'd like to have such a xml: namename

public class WrapperTest {

public static void main(String[] args) throws JsonGenerationException,
        JsonMappingException, IOException {
    ObjectMapper mapper = new XmlMapper();
    Bean bean = new Bean();
    BeanInfo beanInfo = new BeanInfo();
    beanInfo.setName("name");
    BeanInfo beanOther = new BeanInfo();
    beanOther.setName("name");
    bean.setBeanInfo(new BeanInfo[] { beanInfo });
    bean.setBeanOther(new BeanInfo[] { beanOther });
    String output = mapper.writeValueAsString(bean);
    System.out.println(output);
}

@JacksonXmlRootElement(localName = "output")
private static class Bean {
    private BeanInfo[] beanInfo;
    private BeanInfo[] beanOther;

    @JacksonXmlElementWrapper(localName = "beanInfo")
    @JacksonXmlProperty(localName = "item")
    public BeanInfo[] getBeanInfo() {
        return beanInfo;
    }

    @JacksonXmlElementWrapper(localName = "beanInfo")
    public void setBeanInfo(BeanInfo[] beanInfo) {
        this.beanInfo = beanInfo;
    }

    @JacksonXmlElementWrapper(localName = "beanOther")
    @JacksonXmlProperty(localName = "item")
    public BeanInfo[] getBeanOther() {
        return beanOther;
    }
    @JacksonXmlElementWrapper(localName = "beanOther")
    public void setBeanOther(BeanInfo[] beanOther) {
        this.beanOther = beanOther;
    }
}

private static class BeanInfo {
    private String name;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

}

This example give getter definition conflict.

If I change

@JacksonXmlElementWrapper(localName = "beanOther")
        @JacksonXmlProperty(localName = "item2")
        public BeanInfo[] getBeanOther() {
}

then all work fine and I've got

<output><beanInfo><item><name>name</name></item></beanInfo><beanOther><item2><name>name</name></item2></beanOther></output>

but if I try to deserialize it then I've got setter definition conflict...

cowtowncoder commented 12 years ago

Yes, I can reproduce this issue, added a unit test. Hope to resolve it.

cowtowncoder commented 11 years ago

I now understand what is happening -- property names ("inner" names) are being used for property maps, and result in conflicts, before wrappers would untangle everything. Not sure how to resolve this, but this might be solvable along with the question of whether wrapper should or should not be used for JSON.

madrob commented 6 years ago

This issue has been around for a while, I'm currently upgrading my application from org.codehaus.jackson v1 to com.fasterxml.jackson v2 and hitting this as a regression. Does anybody have a workaround or an ETA for a fix on it?

cowtowncoder commented 6 years ago

@madrob Unlikely this would get resolved any time soon.

mikaelhg commented 6 years ago

Bumped into this issue in a project where I'm trying to replace GSON for JSON and xstream for XML with Jackson. Since I can't wrap the objects, I'll try to customize XmlSerializerProvider to overcome this, either directly or through annotation processing.

RikkiGibson commented 6 years ago

@mikaelhg did you find a solution for this that didn't involve wrapping the objects?

mikaelhg commented 6 years ago

@RikkiGibson Yes, but since this was the very last commit I made for my previous employer, I don't have access to the partial implementation which I got semi-working. Customizing collection XML serialization to look exactly like xstream was a giant PITA, and required reading through a lot of both Jackson XML and the relevant core code, and then stepping through it with a debugger. Maybe I'm just stupid, YMMV.

RikkiGibson commented 6 years ago

I doubt you are :) But since I have full control over my model classes and don't need superfast serialization performance I'm considering just using JAXB for XML serialization and using Jackson for JSON. Thanks for letting me know.

zhangqunshi commented 4 years ago

how to solve this problem?

Vincent3039 commented 2 months ago

Since nobody post a response, i propose a solution to wrapp list with a class and using @JacksonXmlElementWrapper(useWrapping = false).


@JacksonXmlRootElement(localName = "output")
@Getter
@Setter
public class Bean {
    @JacksonXmlProperty(localName = "beanInfo")
    private BeanInfoList beanInfo;
    @JacksonXmlProperty(localName = "beanOther")
    private BeanInfoList beanOther;
}

@Getter
@Setter
public class BeanInfoList {
    @JacksonXmlElementWrapper(useWrapping = false)
    @JacksonXmlProperty( localName = "item")
    private BeanInfo[] bean;
}

@Getter
@Setter
public class BeanInfo {
    private String name;
}

public static void main(String[] args) throws JsonGenerationException,
        JsonMappingException, IOException {
    ObjectMapper mapper = new XmlMapper();
    Bean bean = new Bean();
    BeanInfo beanInfo = new BeanInfo();
    beanInfo.setName("name");
    BeanInfo beanOther = new BeanInfo();
    beanOther.setName("name");
    BeanInfoList beanInfoList = new BeanInfoList();
    beanInfoList.setBean(new BeanInfo[] { beanInfo });
    bean.setBeanInfo(beanInfoList);
    BeanInfoList beanOtherList = new BeanInfoList();
    beanOtherList.setBean(new BeanInfo[] { beanOther });
    bean.setBeanOther(beanOtherList);
    String output = mapper.writeValueAsString(bean);
    System.out.println(output);
}

This will post as result

`

name
<beanOther>
  <item>
    <name>name</name>
  </item>
</beanOther>

`