Reputation: 1168
I am writing an application that needs to make a POST request with XML. I have generated XML classes from XSD schema and am now trying to generate the body of said request with XmlMapper.
I have the following classes:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "header", propOrder = {
"createdOn"
})
public class MessageHeader {
@XmlElement(required = true)
protected MessageCreatedOn createdOn;
...
...
...
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "messageCreatedOn")
public class MessageCreatedOn {
@XmlAttribute(name = "value", required = true)
@XmlSchemaType(name = "dateTime")
protected XMLGregorianCalendar value;
...
...
...
}
And the following XmlMapper configuration:
final XmlMapper objectMapper = XmlMapper.builder()
.defaultUseWrapper(false)
.build();
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"));
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
String result = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(messageBase);
With dependency:
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.10.3</version>
</dependency>
I want result to be:
<header>
<createdOn value="2021-08-18T14:06:14.493+03:00"/>
</header>
But the result is:
<header>
<createdOn>
<value>2021-08-18T14:06:14.493+03:00</value>
</createdOn>
</header>
What should I change to get the value
to be an attribute to createdOn
element.
Upvotes: 2
Views: 1733
Reputation: 125232
As you are using JAXB annotations as the metadata you need to instruct Jackson to use those. Else it will use the default, the Jackson annotations for XML or when absent, everything will become an element.
To enable JAXB annotation processing add the JaxbAnnotationModule
to the XmlMapper
. This lets Jackson use the JAXB annotation to provide the mapping metadata.
final XmlMapper objectMapper = XmlMapper.builder()
.defaultUseWrapper(false)
.defaultDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"))
.serializationInclusion(JsonInclude.Include.NON_EMPTY)
.addModule(new JaxbAnnotationModule())
.build();
Also ideally your XmlMapper
should be a singleton bean and not created each time you need it. Another note if you are using Spring, you should really be using a RestTemplate
which handles the (un)marshalling for you.
Upvotes: 3