JavaRush/Курсы/Java Collections/Сложная сериализация в XML, JAXB (вложенные классы и т.д....

Сложная сериализация в XML, JAXB (вложенные классы и т.д.)

Открыта

— Так вот. Как ты уже, наверное, догадался — это еще не все.

Сейчас я тебе расскажу об еще нескольких аспектах JAXB. Но начнем мы, как и в случае с JSON, с коллекций.

При десериализации коллекций в JAXB тоже возникает неопределенность, какую именно коллекцию (ArrayList, LinkedList, Vector, …) подставить в переменную типа List? И опять ответ на этот вопрос дают аннотации.

Тут все довольно просто. Если тип коллекции не задан в аннотации к ней, тогда JAXB попробует подобрать самую подходящую коллекцию – на основе типа. Для List это будет ArrayList, для Map – HashMap и т.д.

На самом деле тут гораздо меньше проблем, чем в случае с JSON, т.к. у каждого класса есть его уникальный тэг, а по тэгу можно точно определить – что это за класс.

Например, если надо десериализовать группу элементов, которые унаследованы от общего предка, для этого используется аннотация @XmlAny:

Конвертация объекта из XML
public static void main(String[] args) throws JAXBException
{
 String xmldata = "<zoo><cat/><cat/><dog/><cat/></zoo>";
 StringReader reader = new StringReader(xmldata);

 JAXBContext context = JAXBContext.newInstance(Cat.class, Zoo.class, Dog.class);
 Unmarshaller unmarshaller = context.createUnmarshaller();

 Zoo zoo = (Zoo) unmarshaller.unmarshal(reader);
}
Класс, объект которого десериализуется из XML
@XmlType(name = "zoo")
@XmlRootElement
class Zoo
{
 @XmlAnyElement
 public List<Object> animals;
}

@XmlType(name = "cat")
@XmlRootElement
class Cat
{
 public String name;
 public int age;
 public int weight;

 Cat()
 {
 }
}

@XmlType(name = "dog")
@XmlRootElement
class Dog
{
 public String name;
 public int age;
 public int weight;

 Dog()
 {
 }

Если коллекция помечена аннотацией @XmlAnyElement, то в нее могут быть помещены любые подходящие объекты. JAXB Unmarshaller при этом обращает внимание на тэги.

При этом последовательность тэгов «<zoo><cat/><cat/><dog/><cat/></zoo>» будет превращена в набор объектов Cat, Cat, Dog, Cat.

— Ожидаемо, в общем.

— Ага. О, кстати, вот еще что. Если ты десериализуешь смесь текста и тэгов, для этого надо использовать аннотацию @XmlMixed.

Пример такого XML:

Пример XML, для которого нужно использовать аннотацию @XmlMixed
<data>
<items>
 test 1
<item/>
 text 2
<item>
 name
</item>
 text 3
</items>
</data>

— Ого. А я и забыл, что такой XML бывает. Привык, что все так красиво, тэги вложены, все дела.

— Бывает. И даже на этот случай у JAXB есть аннотация!

— Отлично. А я вот, кстати, хотел спросить, а как сериализуются enum?

— Хороший вопрос! Молодец! Я-то как раз упустил эту тему.

Для enum существует специальная аннотация @XmlEnum, которой надо помечать enum. В ней же можно указать – будут значения представлены в виде чисел или строк.

Также есть специальная аннотация @XmlEnumValue, которая позволяет задать специальное значение, которое будет соответствовать данному значению enum’а.

Примеры:

Числа Строки
@XmlType @XmlEnum(Integer.class)
public enum Code
{
 @XmlEnumValue("1")
  START,

 @XmlEnumValue("2")
  INPROGRESS,

 @XmlEnumValue("3")
  FINISH

 @XmlEnumValue("-1")
  ERROR
}
@XmlType @XmlEnum(String.class)
public enum Card
{
 @XmlEnumValue("Пика")
  SPADES,

 @XmlEnumValue("Бубна")
  DIAMONDS,

 @XmlEnumValue("Черва")
  HEARTS,

 @XmlEnumValue("Трефа")
  CLUBS
}

— Ух ты. Не могу представить, где мне это может понадобиться, но думаю, что это очень полезная штука. А главное – не обязательно придерживается стандартных строковых или числовых значений.

— Ага. Это полезно, когда ты, например, пишешь программу, которая обменивается сообщениями, скажем, с сервером Facebook, и у них свой заданный набор значений. Тебе достаточно просто прописать их у своего enum и все заработает.

— Это же замечательно. Мне определенно нравится JAXB.

— Отлично. Тогда на сегодня все. Иди — отдыхай.

Комментарии (77)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
SomeBody098веник в бане
29 сентября 2024, 07:02
прочитайте эту замечательную статью про xml, и ее продолжения
2 марта 2024, 16:24
И что это? Вообще 0 объяснений , куда писать @XmlMixed? какой текст? Что происходит ?
Aglaya
Уровень 47
17 июля 2022, 03:28
Как произносится JAXB?
tohik
Уровень 44
17 июля 2022, 11:56
джаксб
Ilia lenskii
Уровень 32
11 сентября 2022, 16:48
Это же аббревиатура, а для них работает правило > буквенные аббревиатуры читаются по названию букв
Elidriel
Уровень 1
25 марта 2022, 08:31
Так... Ладно... из листания разных источников в интернете я понял что в современных реалиях чаще пользуются JSON, чем XML понятное дело, что с XML ознакомиться нужно, хотя бы чтобы знать что отвечать на собесах, но упираться в доскональное его изучение на мой взгляд смысла нет
Ilia lenskii
Уровень 32
11 сентября 2022, 16:54
Вы не видите всей картины. XML гораздо больше чем кажется, скажем HTML (подмножество XML), docx и прочие аналоги, SOAP в финансовом секторе.
Egor
Уровень 66
22 января 2024, 08:45
XML вижу в некоторых вакансиях на джуна. Лучше сначала XML осваивать
Anonymous #3241009
Уровень 43
Expert
17 марта 2024, 14:58
если работаешь с электронным документооборотом то xml очень много, очень много фин отчетности отправляется xml
Denis Odesskiy Full Stack Developer
6 октября 2024, 20:21
XML надо знать в обязательном порядке. Он намного гибче и универсальнее json и используется далеко не только в сериализации. jaxb тоже, пожалуй более мощный инструмент чем json (благодаря xml) позволяющий выполниять более глубокие настройки. json немного моднявие и хайповие (благодаря хайповости сегодня того же js) и чуточку легковеснее. Но это лишь мода, а она как известна временна и проходяща, потому знать надо и то и другое имхо...
hidden #2595317
Уровень 45
20 февраля 2022, 17:14
Например, если надо десериализовать группу элементов, которые унаследованы
от общего предка, для этого используется аннотация @XmlAny:
И хрен с ним, что класса Анимал нет вообще, но и никакого наследования не наблюдается.
Hidden #213 Урoвень 13 (Forever&Ever)
6 марта 2022, 13:19
угу... чем дальше, тем больше ошибок в лекциях😐 Такое чувство, что создатели JR просто выдохлись и забили на всё. Скопипастили код абы как... практически под каждой лекцией пишут об грубых ошибках (и этим постам уже по 3-4 года!)😖
Andrey EliseevJava Developer в СберТех
20 мая 2022, 12:05
Друзья, посмотрите внимательно дженерики в лист (List<Object> animals). Это значит что туда вообще все что угодно можно добавлять, а animals-просто его название)) я тоже сначала не увидел 😅
ВиталийРаботает в поте лица
17 февраля 2022, 20:38
Последнее предложение чуть по-другому не прочитал. Было бы в контексте 😁
KesЧайник в Банк
30 октября 2021, 02:46
Анализирую лекцию
Дмитрий
Уровень 41
1 июля 2021, 09:13
Спасибо - нифига не понятно
При этом последовательность тэгов «<zoo><cat/><cat/><dog/><cat/><zoo>» будет превращена в набор объектов Cat, Cat, Dog, Cat.
почему zoo только открывающий тег? почему остальные теги - закрывающие?
Maks PanteleevJava Developer в Bell Integrator
5 июля 2021, 10:08
запись <cat/> равнозначна записи <cat></cat>, это пустой тег. Не надо путать <cat/> и </cat> )
Дмитрий
Уровень 41
12 июля 2021, 13:03
а что по zoo ?
Дмитрий
Уровень 41
12 июля 2021, 13:03
вижу, уже исправили )))
VitalyK #1116124
Уровень 1
21 июня 2021, 15:54
скажите пожалуйста - тэг и элемент это одно и то же ?
Maks PanteleevJava Developer в Bell Integrator
5 июля 2021, 10:09
нет, тэг это тэг, а внутри тэга уже либо элемент либо атрибут либо все вместе либо ничего) как я понял, тэг = класс в джаве, а элементы и атрибуты это поля класса
Hidden #213 Урoвень 13 (Forever&Ever)
6 марта 2022, 13:02
Часто приходится Тэгать сейчас?😏
Maks PanteleevJava Developer в Bell Integrator
6 марта 2022, 15:36
примерно никогда)
Hidden #213 Урoвень 13 (Forever&Ever)
6 марта 2022, 16:02
😝 врёшь ты мне! Прямо сейчас наверное сидишь и тэгаешь
Maks PanteleevJava Developer в Bell Integrator
6 марта 2022, 16:09
а, так ты про онанизм? тогда да, часто конечно))))
Hidden #213 Урoвень 13 (Forever&Ever)
6 марта 2022, 16:37
Кто о чём😅😂 Я о граффити! Тэгать - рисовать граффити. Вандал🚫
Maks PanteleevJava Developer в Bell Integrator
6 марта 2022, 16:56
не, такое не делаю я) в школе ребята любили, а я никогда и баллончик то в руках не держал, хотя рэпчину слушал
Hidden #213 Урoвень 13 (Forever&Ever)
6 марта 2022, 17:15
хммм... очень странно🤨 Парень из столицы, слушал рэп\хип-хоп и что бы ни разу не держал баллончик в руках🤨 Вот 100% виноваты компуХтеры! или девушки! Одно из двух =D
Maks PanteleevJava Developer в Bell Integrator
6 марта 2022, 17:29
Я просто ненавижу рисовать, ваще не мое, поэтому самые долгие отношения в жизни оба раза были с художницами)))
Hidden #213 Урoвень 13 (Forever&Ever)
6 марта 2022, 18:40
Тянет к творческим людям? :) А они спрашивали у тебя: "А ты точно Программист?!" 🥰
Maks PanteleevJava Developer в Bell Integrator
6 марта 2022, 18:49
ты думаешь, что двое самых долгих отношений у меня уместились в один год примерно?)) потому что программистом я стал совсем недавно)) но нет, не тянет, это как будто бы карма)
15 июня 2021, 18:43
Дополнение к лекции. JAXB напрямую не поддерживает java-интерфейсы (как и обобщенные типы). Поддерживается только интерфейс java.util.List и java.util.Map Если число реализаций интерфейса не велико и вероятность появления новых не очень высока, то удобно использовать аннотацию @XmlElements:
interface Animal {
}

@XmlRootElement
class Cat implements Animal {
    @XmlTransient public String name = "cat";
    @XmlTransient public int age;
    @XmlTransient public int weight;
}

@XmlRootElement
class Dog implements Animal {
    @XmlTransient public String name = "dog";
    @XmlTransient public int age;
    @XmlTransient public int weight;
}

@XmlRootElement
class Zoo {
    private Animal cat = new Cat();
    private Animal cat1 = new Cat();
    private Animal dog = new Dog();
    private Animal cat2 = new Cat();

    @XmlElements({
            @XmlElement(name = "cat", type = Cat.class),
            @XmlElement(name = "dog", type = Dog.class)
    })
    private List<Animal> animals = new ArrayList<>();

    Zoo() {
        animals.add(cat);
        animals.add(cat1);
        animals.add(dog);
        animals.add(cat2);
    }

    public static void main(String[] args) throws JAXBException, IOException {
        Zoo zoo = new Zoo();
        JAXBContext context = JAXBContext.newInstance(Zoo.class, Cat.class, Dog.class);
        Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        marshaller.marshal(zoo, System.out);
    }
}
продолжение в комментарии
15 июня 2021, 18:44
В самом общем случае, как рекомендует документация, следует применять аннотацию @XmlRootElement вместе с @XmlAnyElement, что обеспечит большую гибкость в случае появления новых реализаций при большом количестве уже существующих.
//код

@XmlRootElement
class Zoo {
    private Animal cat = new Cat();
    private Animal cat1 = new Cat();
    private Animal dog = new Dog();
    private Animal cat2 = new Cat();

    @XmlAnyElement
    private List<Animal> animals = new ArrayList<>();

    Zoo() {
        animals.add(cat);
        animals.add(cat1);
        animals.add(dog);
        animals.add(cat2);
    }

   //код