├── pom.xml └── src └── main ├── java │ └── mtitek │ ├── jackson │ │ └── marshalling │ │ ├── TestJsonMarshaller.java │ │ ├── TestJsonUnmarshaller.java │ │ ├── TestXMLMarshaller.java │ │ ├── TestXMLUnmarshaller.java │ │ ├── jaxb │ │ │ ├── TestMarshaller.java │ │ │ └── payload │ │ │ ├── Payload.java │ │ │ ├── PayloadParameter.java │ │ │ └── package-info.java │ │ └── payload │ │ ├── Payload.java │ │ └── PayloadParameter.java │ └── jaxb │ └── utils │ ├── JAXBContextUtils.java │ ├── MarshallerUtils.java │ ├── ResourceUtils.java │ ├── SchemaUtils.java │ └── UnmarshallerUtils.java └── resources ├── logback.xml ├── payload.json ├── payload.xml └── payload.xsd
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>mtitek.jackson.marshalling</groupId> <artifactId>mtitek-jackson-marshalling</artifactId> <version>1.0.0-SNAPSHOT</version> <name>mtitek-jackson-marshalling</name> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>23</java.version> <maven.compiler.source>23</maven.compiler.source> <maven.compiler.target>23</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.18.0</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.19.0</version> </dependency> <dependency> <groupId>jakarta.xml.bind</groupId> <artifactId>jakarta.xml.bind-api</artifactId> <version>4.0.2</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.19.1</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> <version>2.19.1</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.module</groupId> <artifactId>jackson-module-jaxb-annotations</artifactId> <version>2.19.1</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.4.14</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.14.0</version> <configuration> <source>${maven.compiler.source}</source> <target>${maven.compiler.target}</target> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>3.8.1</version> <executions> <execution> <id>dependency-analyze</id> <goals> <goal>analyze</goal> </goals> <phase>package</phase> </execution> </executions> </plugin> </plugins> </build> </project>
package mtitek.jaxb.utils; import java.io.IOException; import java.io.InputStream; import org.apache.commons.io.IOUtils; public class ResourceUtils { private ResourceUtils() { } public static InputStream getResourceAsStream(final String fileName) { return Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName); } public static String getResourceAsString(final String fileName) throws IOException { try (final InputStream inputStream = ResourceUtils.getResourceAsStream(fileName)) { return IOUtils.toString(inputStream, "UTF-8"); } } }
package mtitek.jaxb.utils; import java.util.Optional; import jakarta.xml.bind.JAXBContext; import jakarta.xml.bind.JAXBException; import org.apache.commons.lang3.ArrayUtils; public class JAXBContextUtils { private JAXBContextUtils() { } public static <T> Optional<JAXBContext> getJAXBContext(final Class<T> mainClassToBeBound, final Class<?>... classesToBeBound) throws JAXBException { return Optional.ofNullable(JAXBContext.newInstance(ArrayUtils.add(classesToBeBound, mainClassToBeBound))); } }
package mtitek.jaxb.utils; import java.io.IOException; import java.util.Optional; import java.util.stream.Stream; import javax.xml.XMLConstants; import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import org.apache.commons.lang3.ArrayUtils; import org.xml.sax.SAXException; public class SchemaUtils { private SchemaUtils() { } public static Optional<Schema> getSchema(final String... filesNames) throws SAXException, IOException { Schema schema = null; StreamSource[] streamSources = null; if (!ArrayUtils.isEmpty(filesNames)) { try { streamSources = Stream.of(filesNames).map(fileName -> ResourceUtils.getResourceAsStream(fileName)) .filter(inputStream -> inputStream != null).map(inputStream -> new StreamSource(inputStream)) .toArray(StreamSource[]::new); if (!ArrayUtils.isEmpty(streamSources)) { final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); schema = schemaFactory.newSchema(streamSources); } } finally { if (!ArrayUtils.isEmpty(streamSources)) { Stream.of(streamSources).forEach(streamSource -> { try { if (streamSource.getInputStream() != null) { streamSource.getInputStream().close(); } } catch (IOException e) { e.printStackTrace(); } }); } } } return Optional.ofNullable(schema); } }
package mtitek.jaxb.utils; import java.io.OutputStream; import java.util.Optional; import jakarta.xml.bind.JAXBContext; import jakarta.xml.bind.JAXBElement; import jakarta.xml.bind.JAXBException; import jakarta.xml.bind.Marshaller; import javax.xml.namespace.QName; public class MarshallerUtils { private MarshallerUtils() { } public static <T> void marshal(final OutputStream outputStream, final T object, final QName qName, final Class<T> mainClassToBeBound, final Class<?>... classesToBeBound) throws JAXBException { final Optional<Marshaller> optionalMarshaller = MarshallerUtils.createMarshaller(mainClassToBeBound, classesToBeBound); if (optionalMarshaller.isPresent()) { Marshaller marshaller = optionalMarshaller.get(); if (qName == null) { marshaller.marshal(object, outputStream); } else { final JAXBElement<T> jaxbElement = new JAXBElement<>(qName, mainClassToBeBound, object); marshaller.marshal(jaxbElement, outputStream); } } else { throw new JAXBException("Failed to create the marshaller!"); } } private static <T> Optional<Marshaller> createMarshaller(final Class<T> mainClassToBeBound, final Class<?>... classesToBeBound) throws JAXBException { final Optional<JAXBContext> jaxbContext = JAXBContextUtils.getJAXBContext(mainClassToBeBound, classesToBeBound); Marshaller marshaller = null; if (jaxbContext.isPresent()) { marshaller = jaxbContext.get().createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); } return Optional.ofNullable(marshaller); } }
package mtitek.jaxb.utils; import java.io.InputStream; import java.util.Optional; import jakarta.xml.bind.JAXBContext; import jakarta.xml.bind.JAXBElement; import jakarta.xml.bind.JAXBException; import jakarta.xml.bind.Unmarshaller; import jakarta.xml.bind.helpers.DefaultValidationEventHandler; import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; public class UnmarshallerUtils { private UnmarshallerUtils() { } public static <T> Optional<T> unmarshal(final InputStream inputStream, final Schema schema, final Class<T> mainClassToBeBound, final Class<?>... classesToBeBound) throws JAXBException { if (inputStream == null) { throw new IllegalArgumentException("InputStream cannot be null"); } final Optional<Unmarshaller> optionalUnmarshaller = UnmarshallerUtils.createUnmarshaller(mainClassToBeBound, classesToBeBound); T instance = null; if (optionalUnmarshaller.isPresent()) { Unmarshaller unmarshaller = optionalUnmarshaller.get(); if (schema != null) { unmarshaller.setSchema(schema); unmarshaller.setEventHandler(new DefaultValidationEventHandler()); } final StreamSource streamSource = new StreamSource(inputStream); final JAXBElement<T> jaxbElement = unmarshaller.unmarshal(streamSource, mainClassToBeBound); if (jaxbElement != null) { instance = jaxbElement.getValue(); } } else { throw new JAXBException("Failed to create the unmarshaller!"); } return Optional.ofNullable(instance); } private static <T> Optional<Unmarshaller> createUnmarshaller(final Class<T> mainClassToBeBound, final Class<?>... classesToBeBound) throws JAXBException { final Optional<JAXBContext> jaxbContext = JAXBContextUtils.getJAXBContext(mainClassToBeBound, classesToBeBound); Unmarshaller unmarshaller = null; if (jaxbContext.isPresent()) { unmarshaller = jaxbContext.get().createUnmarshaller(); } return Optional.ofNullable(unmarshaller); } }
package mtitek.jackson.marshalling.jaxb.payload; import java.util.ArrayList; import java.util.List; import jakarta.xml.bind.annotation.XmlAccessType; import jakarta.xml.bind.annotation.XmlAccessorType; import jakarta.xml.bind.annotation.XmlElement; import jakarta.xml.bind.annotation.XmlElementWrapper; import jakarta.xml.bind.annotation.XmlRootElement; import jakarta.xml.bind.annotation.XmlTransient; import jakarta.xml.bind.annotation.XmlType; @XmlRootElement(name = "payload") @XmlType(name = "payload", propOrder = { "id", "code", "parameters" }) @XmlAccessorType(XmlAccessType.FIELD) public class Payload { @XmlElement(name = "id", required = true) private String id; @XmlElement(name = "code", required = true) private String code; @XmlTransient private String desc; @XmlElementWrapper(name = "parameters") @XmlElement(name = "parameter") private final List<PayloadParameter> parameters = new ArrayList<>(); public String getId() { return id; } public void setId(String value) { this.id = value; } public String getCode() { return code; } public void setCode(String value) { this.code = value; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } public List<PayloadParameter> getParameters() { List<PayloadParameter> copyParameters = new ArrayList<PayloadParameter>(); copyParameters.addAll(this.parameters); return copyParameters; } public void setParameters(final List<PayloadParameter> parameters) { this.parameters.clear(); if (parameters != null) { this.parameters.addAll(parameters); } } @Override public String toString() { return "Payload [id=" + id + ", code=" + code + "]"; } }
package mtitek.jackson.marshalling.jaxb.payload; import jakarta.xml.bind.annotation.XmlAccessType; import jakarta.xml.bind.annotation.XmlAccessorType; import jakarta.xml.bind.annotation.XmlAttribute; import jakarta.xml.bind.annotation.XmlElement; import jakarta.xml.bind.annotation.XmlRootElement; import jakarta.xml.bind.annotation.XmlType; @XmlRootElement(name = "parameter") @XmlType(name = "parameterType", propOrder = { "name", "value" }) @XmlAccessorType(XmlAccessType.FIELD) public class PayloadParameter { @XmlAttribute(name = "id", required = true) private String id; @XmlElement(name = "name", required = true) private String name; @XmlElement(name = "value", required = true) private String value; public String getId() { return id; } public void setId(String value) { this.id = value; } public String getName() { return name; } public void setName(String value) { this.name = value; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } @Override public String toString() { return "PayloadParameter [id=" + id + ", name=" + name + ", value=" + value + "]"; } }
@jakarta.xml.bind.annotation.XmlSchema(namespace = "http://marshalling.jackson.mtitek/payload", elementFormDefault = jakarta.xml.bind.annotation.XmlNsForm.QUALIFIED) package mtitek.jackson.marshalling.jaxb.payload;
package mtitek.jackson.marshalling.payload; import java.util.ArrayList; import java.util.List; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlCData; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @JacksonXmlRootElement(namespace = "http://marshalling.jackson.mtitek/payload", localName = "payload") @JsonPropertyOrder({ "id", "code" }) public class Payload { @JsonProperty("id") @JacksonXmlProperty(isAttribute = false, localName = "id", namespace = "") private String id; @JsonProperty("code") @JacksonXmlProperty(isAttribute = false, localName = "code", namespace = "") private String code; @JsonProperty("label") @JacksonXmlProperty(isAttribute = false, localName = "label", namespace = "") @JacksonXmlCData private String label; @JsonIgnore private String desc; @JacksonXmlElementWrapper(localName = "parameters") @JsonProperty("parameter") private final List<PayloadParameter> parameters = new ArrayList<>(); public String getId() { return id; } public void setId(String value) { this.id = value; } public String getCode() { return code; } public void setCode(String value) { this.code = value; } public String getLabel() { return label; } public void setLabel(String label) { this.label = label; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } public List<PayloadParameter> getParameters() { List<PayloadParameter> copyParameters = new ArrayList<PayloadParameter>(); copyParameters.addAll(this.parameters); return copyParameters; } public void setParameters(final List<PayloadParameter> parameters) { this.parameters.clear(); if (parameters != null) { this.parameters.addAll(parameters); } } @Override public String toString() { return "Payload [id=" + id + ", code=" + code + ", label=" + label + "]"; } }
package mtitek.jackson.marshalling.payload; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @JacksonXmlRootElement(localName = "parameter") @JsonPropertyOrder({ "name", "value" }) public class PayloadParameter { @JsonProperty("id") @JacksonXmlProperty(isAttribute = true, localName = "id", namespace = "") private String id; @JsonProperty("name") @JacksonXmlProperty(isAttribute = false, localName = "name", namespace = "") private String name; @JsonProperty("value") @JacksonXmlProperty(isAttribute = false, localName = "value", namespace = "") private String value; public String getId() { return id; } public void setId(String value) { this.id = value; } public String getName() { return name; } public void setName(String value) { this.name = value; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } @Override public String toString() { return "PayloadParameter [id=" + id + ", name=" + name + ", value=" + value + "]"; } }
<?xml version="1.0" encoding="UTF-8"?> <xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://marshalling.jackson.mtitek/payload" xmlns="http://marshalling.jackson.mtitek/payload" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.1"> <xs:element name="payload"> <xs:complexType> <xs:sequence> <xs:element name="id" type="xs:string" /> <xs:element name="code" type="xs:string" /> <xs:element name="parameters" type="parametersType" minOccurs="0" maxOccurs="1" /> </xs:sequence> </xs:complexType> </xs:element> <xs:complexType name="parametersType"> <xs:sequence> <xs:element name="parameter" type="parameterType" minOccurs="1" maxOccurs="unbounded" /> </xs:sequence> </xs:complexType> <xs:complexType name="parameterType"> <xs:all> <xs:element name="name" type="xs:string" /> <xs:element name="value" type="xs:string" /> </xs:all> <xs:attribute name="id" type="xs:string" /> </xs:complexType> </xs:schema>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <payload> <id>123</id> <code>xyz</code> <parameters> <parameter id="11"> <name>bar</name> <value>foo</value> </parameter> <parameter id="22"> <value>ti</value> <name>ta</name> </parameter> </parameters> </payload>
{ "id": "111", "code": "222", "label": "label payload", "parameters": [ { "name": "ddd", "value": "eee", "id": "111" }, { "name": "rrr", "value": "ttt", "id": "222" } ] }
<configuration> <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender"> <target>System.out</target> <encoder> <pattern>%p [%d{ISO8601}] %c - %m%n </pattern> </encoder> </appender> <logger name="mtitek.jackson.marshalling" level="INFO" /> <root level="info"> <appender-ref ref="stdout" /> </root> </configuration>
package mtitek.jackson.marshalling; import java.util.ArrayList; import java.util.List; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.dataformat.xml.JacksonXmlModule; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import mtitek.jackson.marshalling.payload.Payload; import mtitek.jackson.marshalling.payload.PayloadParameter; /** * Demonstrates XML marshalling using Jackson's native XML annotations. * This approach provides full control over XML output including namespaces and CDATA. */ public class TestXMLMarshaller { public static void main(String[] args) throws Exception { // Create sample payload with test data final Payload payload = initPayload(); // Configure Jackson XML module JacksonXmlModule xmlModule = new JacksonXmlModule(); // Disable default wrapper elements for better XML structure control xmlModule.setDefaultUseWrapper(false); // Create XML mapper instance ObjectMapper objectMapper = new XmlMapper(xmlModule); // Enable indented output for human-readable XML objectMapper.enable(SerializationFeature.INDENT_OUTPUT); // Convert payload to XML string and display System.out.println(objectMapper.writeValueAsString(payload)); } /** * Initializes a sample Payload object with test data. * Includes label field to demonstrate CDATA handling. * @return Populated Payload instance */ private static Payload initPayload() { final Payload payload = new Payload(); // Set main payload attributes payload.setId("1"); payload.setCode("111"); payload.setLabel("aa vvv ddd"); // Will be wrapped in CDATA payload.setDesc("transient"); // Ignored due to @JsonIgnore // Build parameter collection final List<PayloadParameter> parameters = new ArrayList<>(); // Create first parameter with attribute and elements { final PayloadParameter parameter = new PayloadParameter(); parameter.setId("1"); // XML attribute parameter.setName("aaa"); // XML element parameter.setValue("bbb"); // XML element parameters.add(parameter); } // Create second parameter { final PayloadParameter parameter = new PayloadParameter(); parameter.setId("2"); parameter.setName("ccc"); parameter.setValue("ddd"); parameters.add(parameter); } // Assign parameters to payload payload.setParameters(parameters); return payload; } }Output:
<payload xmlns="http://marshalling.jackson.mtitek/payload"> <id xmlns="">1</id> <code xmlns="">111</code> <label xmlns=""><![CDATA[aa vvv ddd]]></label> <parameters xmlns=""> <parameter id="1"> <name>aaa</name> <value>bbb</value> </parameter> <parameter id="2"> <name>ccc</name> <value>ddd</value> </parameter> </parameters> </payload>
package mtitek.jackson.marshalling; import java.io.IOException; import java.io.InputStream; import jakarta.xml.bind.JAXBException; import org.xml.sax.SAXException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.xml.JacksonXmlModule; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import mtitek.jackson.marshalling.payload.Payload; import mtitek.jaxb.utils.ResourceUtils; /** * Demonstrates XML unmarshalling using Jackson to convert XML documents * into Java objects with automatic property mapping. */ public class TestXMLUnmarshaller { public static void main(String[] args) throws SAXException, IOException, JAXBException { // Load XML file from classpath resources try (final InputStream inputStream = ResourceUtils.getResourceAsStream("payload.xml")) { // Configure Jackson XML module JacksonXmlModule xmlModule = new JacksonXmlModule(); // Disable wrapper elements to match XML structure xmlModule.setDefaultUseWrapper(false); // Create XML mapper for parsing ObjectMapper objectMapper = new XmlMapper(xmlModule); // Parse XML stream into Payload object final Payload payload = objectMapper.readValue(inputStream, Payload.class); // Display the unmarshalled payload object System.out.println(payload); // Display the parameters collection System.out.println(payload.getParameters()); } } }Output:
Payload [id=123, code=xyz, label=null] [PayloadParameter [id=11, name=bar, value=foo], PayloadParameter [id=22, name=ta, value=ti]]
package mtitek.jackson.marshalling; import java.util.ArrayList; import java.util.List; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import mtitek.jackson.marshalling.payload.Payload; import mtitek.jackson.marshalling.payload.PayloadParameter; /** * Demonstrates JSON marshalling using Jackson's standard ObjectMapper. * Shows how the same model classes can be used for both XML and JSON output. */ public class TestJsonMarshaller { public static void main(String[] args) throws Exception { // Create test payload with sample data final Payload payload = initPayload(); // Create standard Jackson ObjectMapper for JSON processing ObjectMapper objectMapper = new ObjectMapper(); // Enable pretty printing for readable JSON output objectMapper.enable(SerializationFeature.INDENT_OUTPUT); // Serialize payload to JSON string and print System.out.println(objectMapper.writeValueAsString(payload)); } /** * Creates a sample Payload object with test data for JSON serialization. * @return Configured Payload with parameters and label */ private static Payload initPayload() { final Payload payload = new Payload(); // Set basic payload properties payload.setId("1"); payload.setCode("111"); payload.setLabel("aa vvv ddd"); // Included in JSON output payload.setDesc("transient"); // Excluded due to @JsonIgnore // Create parameter list final List<PayloadParameter> parameters = new ArrayList<>(); // First parameter with JSON property mapping { final PayloadParameter parameter = new PayloadParameter(); parameter.setId("1"); parameter.setName("aaa"); parameter.setValue("bbb"); parameters.add(parameter); } // Second parameter { final PayloadParameter parameter = new PayloadParameter(); parameter.setId("2"); parameter.setName("ccc"); parameter.setValue("ddd"); parameters.add(parameter); } // Set parameters collection payload.setParameters(parameters); return payload; } }Output:
{ "id" : "1", "code" : "111", "label" : "aa vvv ddd", "parameter" : [ { "name" : "aaa", "value" : "bbb", "id" : "1" }, { "name" : "ccc", "value" : "ddd", "id" : "2" } ] }
package mtitek.jackson.marshalling; import java.io.IOException; import java.io.InputStream; import jakarta.xml.bind.JAXBException; import org.xml.sax.SAXException; import com.fasterxml.jackson.databind.ObjectMapper; import mtitek.jackson.marshalling.payload.Payload; import mtitek.jaxb.utils.ResourceUtils; /** * Demonstrates JSON unmarshalling using Jackson to deserialize JSON documents * into Java objects with automatic type conversion and property mapping. */ public class TestJsonUnmarshaller { public static void main(String[] args) throws SAXException, IOException, JAXBException { // Load JSON file from classpath resources try (final InputStream inputStream = ResourceUtils.getResourceAsStream("payload.json")) { // Create standard Jackson ObjectMapper for JSON processing ObjectMapper objectMapper = new ObjectMapper(); // Deserialize JSON stream into Payload object final Payload payload = objectMapper.readValue(inputStream, Payload.class); // Print the deserialized payload object System.out.println(payload); // Print the parameters collection to verify proper mapping System.out.println(payload.getParameters()); } } }Output:
Payload [id=111, code=222, label=label payload] [PayloadParameter [id=111, name=ddd, value=eee], PayloadParameter [id=222, name=rrr, value=ttt]]
package mtitek.jackson.marshalling.jaxb; import java.util.ArrayList; import java.util.List; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.dataformat.xml.JacksonXmlModule; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule; import mtitek.jackson.marshalling.jaxb.payload.Payload; import mtitek.jackson.marshalling.jaxb.payload.PayloadParameter; /** * Demonstrates how to use Jackson with existing JAXB annotations. * This approach allows migration from JAXB to Jackson without changing model classes. */ public class TestMarshaller { public static void main(String[] args) throws Exception { // Create sample payload object with test data final Payload payload = initPayload(); // Configure Jackson XML module JacksonXmlModule xmlModule = new JacksonXmlModule(); // Disable default wrapper elements for collections xmlModule.setDefaultUseWrapper(false); // Create XML mapper with the configured module ObjectMapper objectMapper = new XmlMapper(xmlModule); // Enable pretty printing for readable output objectMapper.enable(SerializationFeature.INDENT_OUTPUT); // Register JAXB annotation module to process existing JAXB annotations objectMapper.registerModule(new JaxbAnnotationModule()); // Marshall the payload to XML string and print System.out.println(objectMapper.writeValueAsString(payload)); } /** * Creates a sample Payload object with test data for demonstration. * @return Configured Payload instance with parameters */ private static Payload initPayload() { final Payload payload = new Payload(); // Set basic payload properties payload.setId("1"); payload.setCode("111"); payload.setDesc("transient"); // This field is marked as @XmlTransient // Create parameter list final List<PayloadParameter> parameters = new ArrayList<>(); // Add first parameter { final PayloadParameter parameter = new PayloadParameter(); parameter.setId("1"); parameter.setName("aaa"); parameter.setValue("bbb"); parameters.add(parameter); } // Add second parameter { final PayloadParameter parameter = new PayloadParameter(); parameter.setId("2"); parameter.setName("ccc"); parameter.setValue("ddd"); parameters.add(parameter); } // Set parameters to payload payload.setParameters(parameters); return payload; } }Output:
<Payload> <id>1</id> <code>111</code> <desc>transient</desc> <parameters> <id>1</id> <name>aaa</name> <value>bbb</value> </parameters> <parameters> <id>2</id> <name>ccc</name> <value>ddd</value> </parameters> </Payload>