— Так ось. Як ти вже, мабуть, здогадався — це ще не все.

Зараз я тобі розповім про ще кілька аспектів 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< /span>);
 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.

— Чудово. Тоді сьогодні все. Іди — відпочивай.