- Сериализация и десериализация XML с Джексоном
- 2. Объект XmlMapper
- 3. Сериализация Java в XML
- 3.1. Сериализация в строку XML
- 3.2. Сериализация в файл XML
- 4. Десериализовать XML в Java
- 4.1. Десериализовать из строки XML
- 4.2. Десериализовать из XML-файла
- 5. Обработка элементов с заглавными буквами
- 5.1. Десериализовать из строки XML
- 5.2. Сериализация в строку XML
- 6. Сериализация списка в XML
- 7. Десериализовать XML в список
- 8. Заключение
- Jackson XML Mapper
- Overview
- Annotations
- Mapping Root Element
- Mapping XML Property (Attribute / Element)
- Mapping Collection
- Configuration of XML Mapper
- Conclusion
Сериализация и десериализация XML с Джексоном
В этом руководстве мы узнаем , как сериализовать объекты Java в XML-данные с помощью Jackson 2.x и десериализовать их обратно в POJO .
Мы сосредоточимся на базовой операции, которая не требует особой сложности или настройки.
2. Объект XmlMapper
XmlMapper — это основной класс из Jackson 2.x, который помогает нам в сериализации, поэтому нам нужно создать его экземпляр:
XmlMapper mapper = new XmlMapper();
Этот преобразователь доступен в jar -файле jackson-dataformat-xml , поэтому мы должны добавить его в качестве зависимости к нашему pom.xml :
dependency> groupId>com.fasterxml.jackson.dataformatgroupId> artifactId>jackson-dataformat-xmlartifactId> version>2.11.1version> dependency>
3. Сериализация Java в XML
XmlMapper — это подкласс ObjectMapper, который используется в сериализации JSON; однако он добавляет в родительский класс некоторые специфичные для XML настройки.
Давайте посмотрим, как использовать его для реальной сериализации. Давайте сначала создадим класс Java:
class SimpleBean private int x = 1; private int y = 2; //standard setters and getters >
3.1. Сериализация в строку XML
Мы можем сериализовать наш объект Java в строку XML :
@Test public void whenJavaSerializedToXmlStr_thenCorrect() throws JsonProcessingException XmlMapper xmlMapper = new XmlMapper(); String xml = xmlMapper.writeValueAsString(new SimpleBean()); assertNotNull(xml); >
SimpleBean> x>1x> y>2y> SimpleBean>
3.2. Сериализация в файл XML
Мы также можем сериализовать наш объект Java в файл XML:
@Test public void whenJavaSerializedToXmlFile_thenCorrect() throws IOException XmlMapper xmlMapper = new XmlMapper(); xmlMapper.writeValue(new File("simple_bean.xml"), new SimpleBean()); File file = new File("simple_bean.xml"); assertNotNull(file); >
А ниже мы можем увидеть содержимое получившегося файла с именем simple_bean.xml :
SimpleBean> x>1x> y>2y> SimpleBean>
4. Десериализовать XML в Java
В этом разделе мы рассмотрим, как получить объекты Java из XML.
4.1. Десериализовать из строки XML
Как и в случае с сериализацией, мы также можем десериализовать строку XML обратно в объект Java:
@Test public void whenJavaGotFromXmlStr_thenCorrect() throws IOException XmlMapper xmlMapper = new XmlMapper(); SimpleBean value = xmlMapper.readValue("1 2 ", SimpleBean.class); assertTrue(value.getX() == 1 && value.getY() == 2); >
4.2. Десериализовать из XML-файла
Точно так же, если у нас есть файл XML, мы можем преобразовать его обратно в объект Java.
Здесь мы сначала читаем файл во входной поток, а затем преобразуем входной поток в строку с помощью простого служебного метода.
Остальной код аналогичен коду из раздела 4.1.:
@Test public void whenJavaGotFromXmlFile_thenCorrect() throws IOException File file = new File("simple_bean.xml"); XmlMapper xmlMapper = new XmlMapper(); String xml = inputStreamToString(new FileInputStream(file)); SimpleBean value = xmlMapper.readValue(xml, SimpleBean.class); assertTrue(value.getX() == 1 && value.getY() == 2); >
public String inputStreamToString(InputStream is) throws IOException StringBuilder sb = new StringBuilder(); String line; BufferedReader br = new BufferedReader(new InputStreamReader(is)); while ((line = br.readLine()) != null) sb.append(line); > br.close(); return sb.toString(); >
5. Обработка элементов с заглавными буквами
В этом разделе мы обсудим, как работать со сценариями, в которых у нас либо есть XML с заглавными буквами для десериализации, либо нам нужно сериализовать объекты Java в XML с одним или несколькими элементами с заглавными буквами.
5.1. Десериализовать из строки XML
Допустим, у нас есть XML с одним полем с заглавной буквы:
SimpleBeanForCapitalizedFields> X>1X> y>2y> SimpleBeanForCapitalizedFields>
Чтобы правильно обрабатывать элементы с заглавными буквами, нам нужно аннотировать поле «x» аннотацией @JsonProperty :
class SimpleBeanForCapitalizedFields @JsonProperty("X") private int x = 1; private int y = 2; // standard getters, setters >
Теперь мы можем правильно десериализовать строку XML обратно в объект Java:
@Test public void whenJavaGotFromXmlStrWithCapitalElem_thenCorrect() throws IOException XmlMapper xmlMapper = new XmlMapper(); SimpleBeanForCapitalizedFields value = xmlMapper.readValue( "1 2 ", SimpleBeanForCapitalizedFields.class); assertTrue(value.getX() == 1 && value.getY() == 2); >
5.2. Сериализация в строку XML
Аннотируя обязательные поля с помощью @JsonProperty, мы можем правильно сериализовать объект Java в строку XML с одним или несколькими элементами с заглавными буквами:
@Test public void whenJavaSerializedToXmlFileWithCapitalizedField_thenCorrect() throws IOException XmlMapper xmlMapper = new XmlMapper(); xmlMapper.writeValue(new File("target/simple_bean_capitalized.xml"), new SimpleBeanForCapitalizedFields()); File file = new File("target/simple_bean_capitalized.xml"); assertNotNull(file); >
6. Сериализация списка в XML
XmlMapper может сериализовать весь Java-бин в документ. Чтобы преобразовать объект Java в XML, мы возьмем простой пример с вложенным объектом и массивами.
Наша цель — сериализовать объект Person вместе с составным объектом Address в XML.
Наш окончательный XML будет выглядеть примерно так:
Person> firstName>RohanfirstName> lastName>DayelastName> phoneNumbers> phoneNumbers>9911034731phoneNumbers> phoneNumbers>9911033478phoneNumbers> phoneNumbers> address> streetName>Name1streetName> city>City1city> address> address> streetName>Name2streetName> city>City2city> address> Person>
Обратите внимание, что наши телефонные номера инкапсулированы в оболочку phoneNumbers , а наш адрес — нет.
Мы можем выразить этот нюанс через аннотацию @JacksonXMLElementWrapper в нашем классе Person :
public final class Person private String firstName; private String lastName; private ListString> phoneNumbers = new ArrayList>(); @JacksonXmlElementWrapper(useWrapping = false) private ListAddress> address = new ArrayList>(); //standard setters and getters >
На самом деле мы можем изменить имя элемента упаковки с помощью @JacksonXmlElementWrapper(localName = ‘phoneNumbers’). Или, если мы не хотим оборачивать наши элементы, мы можем отключить сопоставление с помощью @JacksonXmlElementWrapper(useWrapping = false) .
Затем мы определим наш тип адреса :
public class Address String streetName; String city; //standard setters and getters >
Джексон позаботится об остальном за нас. Как и раньше, мы можем просто снова вызвать writeValue :
private static final String XML = ". "; @Test public void whenJavaSerializedToXmlFile_thenSuccess() throws IOException XmlMapper xmlMapper = new XmlMapper(); Person person = testPerson(); // test data ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); xmlMapper.writeValue(byteArrayOutputStream, person); assertEquals(XML, byteArrayOutputStream.toString()); >
7. Десериализовать XML в список
Джексон также может читать XML, содержащий списки объектов.
Если мы возьмем тот же самый XML, что и раньше, метод readValue отлично подойдет :
@Test public void whenJavaDeserializedFromXmlFile_thenCorrect() throws IOException XmlMapper xmlMapper = new XmlMapper(); Person value = xmlMapper.readValue(XML, Person.class); assertEquals("City1", value.getAddress().get(0).getCity()); assertEquals("City2", value.getAddress().get(1).getCity()); >
8. Заключение
В этой краткой статье показано, как сериализовать простой POJO в XML и получить POJO из базовых XML-данных.
Мы также изучили, как сериализовать и десериализовать сложные компоненты, содержащие коллекции.
Исходный код, сопровождающий эту статью, доступен на GitHub .
Jackson XML Mapper
How to do Java / XML mapping using Jackson XML Mapper. This article explains the annotations used for root element, property, and collection mapping. Also, the basic configuration of Jackson XML Ma.
Overview
Recently, I used Jackson XML Mapper to create a client SDK for a SOAP service and a mapping for reading Maven test reports (Surefire and Failsafe). I really like the simplicity of the Jackson XML framework. That’s why I would like to share my experience with you. In this article, I will explain briefly different annotations and mapping tricks for XML mapper. After reading, you will understand:
- Different annotations about Jackson XML
- Mapping XML root element
- Mapping XML property (attribute / element)
- Mapping XML collection (with / without wrapping)
- Configuration of XML mapper
Before going further, please ensure you have Java 8+ installed and use the following Maven dependency:
com.fasterxml.jackson.dataformat jackson-dataformat-xml 2.9.8
Annotations
Annotation | Description |
---|---|
@JacksonXmlRootElement | Define root element name in XML. |
@JacksonXmlProperty | Define XML property, can be attribute or element. |
@JacksonXmlElementWrapper | Define wrapper to use for collection types. |
@JacksonXmlCData | Define a CData wrapper. |
@JacksonXmlText | Render an element as plain text. |
Mapping Root Element
Annotation @JacksonXmlRootElement can be used to define name of root element used for the root-level object when serialized, which normally uses name of the type (class). It is similar to JAXB XmlRootElement .
@JacksonXmlRootElement(localName = "user") public class User . >
Mapping XML Property (Attribute / Element)
Annotation @JacksonXmlProperty can be used to provide XML-specific configuration for properties, above and beyond what @JsonProperty contains. It is an alternative to using JAXB annotations. Using boolean property isAttribute can control if the target property is attribute or XML element. By default, the isAttribute value is false.
@JacksonXmlRootElement(localName = "user") public class User @JacksonXmlProperty(isAttribute = true) private int id; @JacksonXmlProperty private String name; public User() <> // Getters and Setters. >
Mapping Collection
Annotation @JacksonXmlElementWrapper is similar to JAXB javax.xml.bind.annotation.XmlElementWrapper , which indicates wrapper element to use (if any) for Collection types (arrays, java.util.Collection ). If defined, a separate container (wrapper) element is used; if not, entries are written without wrapping.
Here’s an example using a separate container (wrapper) element for cards. In other words, the container is cards and the element property is card :
@JacksonXmlRootElement(localName = "user") public class User @JacksonXmlElementWrapper(localName = "cards") @JacksonXmlProperty(localName = "card") private ListString> cards; . >
Now, let’s see another example without using container. In other words, elements are defined directly without going through the container:
@JacksonXmlRootElement(localName = "user") public class User @JacksonXmlElementWrapper(useWrapping = false) @JacksonXmlProperty(localName = "card") private ListString> cards; . >
Configuration of XML Mapper
Object XmlMapper extends ObjectMapper . Therefore, you can use XML in the same way that you use ObjectMapper . For example, register the Java 8 modules to enable the feature of parameter names, Java 8 time, and Java 8 data types. For more information, see https://github.com/FasterXML/jackson-modules-java8.
ObjectMapper m = new XmlMapper(); m.registerModule(new ParameterNamesModule()); m.registerModule(new Jdk8Module()); m.registerModule(new JavaTimeModule());
You can also use method ObjectMapper#configure(. ) to disable or enable a target feature in the mapper.
Conclusion
In this article, we learnt the annotations in Jackson DataFormat XML ( jackson-dataformat-xml ), we saw how to map XML root element, XML property (attribute / element), how to map collection (with / without wrapping), and the configuration of XML mapper. The source code as available in mincong-h/java-examples. Hope you enjoy this article, see you the next time!
This work is licensed under a Attribution 4.0 International license.