Skip to content
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

List serialization without @XmlElementWrapper not working correctly (need to enable XmlMapper.defaultUseWrapper(false)) #589

Closed
toellrich opened this issue Mar 27, 2023 · 3 comments

Comments

@toellrich
Copy link

When serializing a list without @XmlElementWrapper, the list is still wrapped inside another element. The following unit test reproduces the problem:

public class ListWithoutElementWrapperTest {

  @XmlRootElement(name = "employee")
  @XmlType(propOrder = {"hobbies", "id", "firstName", "lastName"})
  @XmlAccessorType(FIELD)
  public static class Employee {

    @XmlElement(name = "hobby")
    List<String> hobbies;

    Integer id;
    String firstName;
    String lastName;
  }

  private Employee employee;

  @BeforeEach
  public void setUp() {
    employee = new Employee();
    employee.id = 1;
    employee.firstName = "Lokesh";
    employee.lastName = "Gupta";
    employee.hobbies = List.of("Swimming", "Playing", "Karate");
  }

  @Test
  public void marshallUsingJaxb() throws JAXBException {
    JAXBContext jaxbContext = JAXBContext.newInstance(Employee.class);
    Marshaller marshaller = jaxbContext.createMarshaller();
    marshaller.setProperty(JAXB_FORMATTED_OUTPUT, TRUE);
    marshaller.setProperty(JAXB_FRAGMENT, Boolean.TRUE);

    String expected =
        """
        <employee>
            <hobby>Swimming</hobby>
            <hobby>Playing</hobby>
            <hobby>Karate</hobby>
            <id>1</id>
            <firstName>Lokesh</firstName>
            <lastName>Gupta</lastName>
        </employee>""";

    StringWriter sw = new StringWriter();
    marshaller.marshal(employee, sw);
    String actual = sw.toString();
    assertEquals(expected, actual);
  }

  /**
   * This test fails
   */
  @Test
  public void writeValueAsStringUsingJackson() throws JsonProcessingException {
    XmlMapper xmlMapper = new XmlMapper();
    xmlMapper.enable(INDENT_OUTPUT);
    xmlMapper.registerModule(new JakartaXmlBindAnnotationModule());

    String expected =
        """
        <employee>
          <hobby>Swimming</hobby>
          <hobby>Playing</hobby>
          <hobby>Karate</hobby>
          <id>1</id>
          <firstName>Lokesh</firstName>
          <lastName>Gupta</lastName>
        </employee>""";

    String actual = xmlMapper.writeValueAsString(employee);
    assertEquals(expected, actual);
  }
}

The second test when using Jackson instead of JAXB fails because the actual output is as follows:

<employee>
  <hobby>
    <hobby>Swimming</hobby>
    <hobby>Playing</hobby>
    <hobby>Karate</hobby>
  </hobby>
  <id>1</id>
  <firstName>Lokesh</firstName>
  <lastName>Gupta</lastName>
</employee>

but I would expect it to be like this:

<employee>
  <hobby>Swimming</hobby>
  <hobby>Playing</hobby>
  <hobby>Karate</hobby>
  <id>1</id>
  <firstName>Lokesh</firstName>
  <lastName>Gupta</lastName>
</employee>

I'm using java 17 and jackson 2.15.0-rc1.

test.zip

@cowtowncoder
Copy link
Member

Yes, Jackson defaults to wrapping Lists by default.
This is different from JAXB defaults, but Jackson is not a JAXB implementation; it has partial support for JAXB annotations but does not have exactly same defaulting.

There is a way to change this default; I forget the method but there's one in XMLMapper.

@toellrich
Copy link
Author

Thanks, found it. It is

XmlMapper mapper = XmlMapper.builder()
   .defaultUseWrapper(false)
   .build();

The issue can be closed.

@cowtowncoder cowtowncoder changed the title List serialization without @XmlElementWrapper not working correctly List serialization without @XmlElementWrapper not working correctly (need to enable XmlMapper.defaultUseWrapper(false)) Mar 29, 2023
@cowtowncoder
Copy link
Member

Thank you for confirming @toellrich !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants