Jackson XML module: Multiple fields representing property error when two collection fields' items have the same name

1.9k Views Asked by At

Required xml:

<bean>
    <paths>
        <path>foo/bar/</path>
        <path>x/y</path>
    <paths>
    <morePaths>
         <path>a/b/c</path>
         <path>j/k/l</path>
    <morePaths>
 <bean>

Beware that the item tags in both collections is the same: "path" whether they're wrapped by different tags: "paths" and "morePaths"

The annotated bean is like (using lombok):

@JacksonXmlRootElement(localName="bean") 
@Accessors(prefix="_")
@NoArgsConstructor @AllArgsConstructor
public static class TestBean {
    @JacksonXmlElementWrapper(localName="paths") @JacksonXmlProperty(localName="path")
    @Getter @Setter private Collection<Path> _pathCol;

    @JacksonXmlElementWrapper(localName="otherPaths") @JacksonXmlProperty(localName="path")
    @Getter @Setter private Collection<Path> _otherPathCol;
}

PROBLEM: When mapping an exception is thrown saying that there're TWO properties mapped to the same tag (path)

@Test
public void test() throws IOException  {
    XmlMapper xmlMapper = new XmlMapper();
    TestBean myBean = new TestBean(Lists.<Path>newArrayList(Path.from("/a/b/c"),
                                                            Path.from("d/e/f")),
                                   Lists.<Path>newArrayList(Path.from("/foo/bar/baz"),
                                                            Path.from("x/y/z")));
    System.out.println("XML: " + xmlMapper.writeValueAsString(myBean));        
}

Exception:

com.fasterxml.jackson.databind.JsonMappingException: Multiple fields representing property "path"

If diferent property names are used, everything works:

@JacksonXmlRootElement(localName="bean") 
@Accessors(prefix="_")
@NoArgsConstructor @AllArgsConstructor
public static class TestBean {
    @JacksonXmlElementWrapper(localName="paths") @JacksonXmlProperty(localName="paths_path")
    @Getter @Setter private Collection<Path> _pathCol;

    @JacksonXmlElementWrapper(localName="otherPaths") @JacksonXmlProperty(localName="otherPaths_path")
    @Getter @Setter private Collection<Path> _otherPathCol;
}

BUT, the xml output is NOT the required one:

<bean>
    <paths>
        <paths_path>foo/bar/</paths_path>
        <paths_path>x/y</paths_path>
    <paths>
    <morePaths>
         <morePaths_path>a/b/c</morePaths_path>
         <morePaths_path>j/k/l</morePaths_path>
    <morePaths>
 <bean>

How can I manage to get items with the same tag in both collections?

NOTE: Actually it's a known issue (see: https://github.com/FasterXML/jackson-dataformat-xml/issues/192) ... but I don't know if there's a workarround

1

There are 1 best solutions below

0
On

Custom serializer can do the job:

TestBean.java

  @JacksonXmlProperty(localName = "paths") // note the name here matches wrapper tag
  @JsonSerialize(contentUsing = AsPathSerializer.class)
  @Getter @Setter private Collection<Path> _pathCol;
  // repeat same way for other collections if needed

AsPathSerializer.java

public class AsPathSerializer extends StdSerializer<Object> {
  private static final QName PATH = new QName("path");

  public AsPathSerializer() {
    super(Object.class);
  }

  @Override
  public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
    final ToXmlGenerator xmlGenerator = (ToXmlGenerator) jsonGenerator;
    xmlGenerator.setNextName(PATH); // override whatever name was
    serializerProvider.defaultSerializeValue(o, jsonGenerator);
  }
}