2

Let's say I have following XML model:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
        "person",
        "user"
})
@XmlRootElement(name = "CUSTOMER")
public class CUSTOMER {
    @XmlElement(name = "PERSON", required = true)
    protected CUSTOMER.PERSON person;
    @XmlElement(name = "USER", required = true)
    protected CUSTOMER.USER user;
 ....
 ....

If I rename class following conventions as:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
        "person",
        "user"
})
@XmlRootElement(name = "CUSTOMER")
public class Customer {
....

And both elements like:

    @XmlElement(name = "PERSON", required = true)
    protected CUSTOMER.PERSON person;
    @XmlElement(name = "USER", required = true)
    protected CUSTOMER.USER user;
    ....

The XML from

new XmlMapper().writerWithDefaultPrettyPrinter().writeValueAsString(customer)) 

looks like this:

<Customer>
  <id>id</id>
  ...
  <person>
    <id>id</id>
    ...
  </person>
  <user>
    <id>id</id>
    ...
  </user>
</Customer>

But I want it to look like this:

<CUSTOMER>
  <id>id</id>
  ...
  <PERSON>
    <id>id</id>
    ...
  </PERSON>
  <USER>
    <id>id</id>
    ...
  </USER>
</CUSTOMER>

Am I doing something wrong? I saw that I can use @JsonProperty and it works, but only for the fields and I feel wrong using JsonProperty on an XML element. Is it okay for my model classes to be named CUSTOMER, PERSON, USER or should I rename them, and if its better to rename them should I use JsonProperty? What about the RootElement?

D.Tomov
  • 1,018
  • 2
  • 15
  • 36

1 Answers1

1

Looks like Jackson is not parsing the JAXB annotations. To fix it, you could use an annotation introspector such as JaxbAnnotationIntrospector:

XmlMapper mapper = new XmlMapper();
mapper.setAnnotationIntrospector(new JaxbAnnotationIntrospector(mapper.getTypeFactory()));

String xml = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(costumer);

Also check the JaxbAnnotationIntrospector documentation, as there are some limitations.


If, for some reason, you intend to use JAXB directly, as you mentioned in the comments, you would have something like:

JAXBContext jaxbContext = JAXBContext.newInstance(Customer.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

StringWriter writer = new StringWriter();
marshaller.marshal(customer, writer);

String xml = writer.toString();

Just bear in mind the JAXBContext should be created once and then reused, as pointed out in this answer.

cassiomolin
  • 124,154
  • 35
  • 280
  • 359
  • This works, is there a XmlMapper equivalent in JAXB I can use instead of retrofitting XmlMapper? – D.Tomov Sep 12 '19 at 11:38
  • 1
    @D.Tomov I'm not sure I'm following your comment. Why don't you use JAXB directly then? – cassiomolin Sep 12 '19 at 11:41
  • I am looking for a way to use these objects with RestTemplate. Is there a JAXB way of making Objects to String. I am not familiar with JAXB. This is an generated class. – D.Tomov Sep 12 '19 at 11:42
  • 1
    @D.Tomov I've updated my answer with an example on how to use JAXB, but I would need more context to give you a more elaborated answer. You always can [ask a new question](https://stackoverflow.com/questions/ask) and provide further details on how you are using `RestTemplate`. – cassiomolin Sep 12 '19 at 11:52
  • 1
    Thank you for your answer If I could upload twice I would. – D.Tomov Sep 12 '19 at 11:58