Jaxb распаковывает последовательность xml для сопоставления

У меня есть два класса Foos и Foo, которые должны быть сериализуемыми/десериализуемыми в/из XML:

@XmlRootElement(name = "foos")
@XmlAccessorType(XmlAccessType.NONE)
@XmlType(name = "Foos", propOrder = { "foo" })
public class Foos {

    protected Map<Foo, Foo> foo;

    public Map<Foo, Foo> getFooMap() {
        if (foo == null) {
            foo = new HashMap<Foo, Foo>();
        }
        return this.foo;
    }

    @XmlElements(value = { @XmlElement })
    public Collection<Foo> getFoo() {
        return getFooMap().values();
    }

}

а также

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Foo", propOrder = { "name" })
public class Foo {

    protected String name;

    public String getName() {
        return name;
    }

    public void setName(String value) {
        this.name = value;
    }

}

По алгоритмическим причинам я не могу использовать List<Foo>, но мне нужен Map<Foo, Foo>. Каждый Foo должен быть помещен в Map как ключ, так и значение.

Маршаллинг объекта Foos в XML работает, потому что у меня есть геттер getFoo, а демаршаллинг из XML — нет. Вероятно, это связано с тем, что демаршаллер не знает, как преобразовать последовательность xml объектов Foo в хэш-карту.

Как мне сообщить об этом демаршаллеру?

Я думаю, мне нужен такой метод (псевдокод):

public void fillMap(XMLSequence<Foo> sequence) {
    for (Foo foo : sequence)
        getFooMap().put(foo, foo);
}

И тогда, вероятно, потребуются некоторые аннотации xml.

Любые подсказки приветствуются!


person Kjara    schedule 08.08.2018    source источник


Ответы (1)


Я нашел способ, используя два поля:

@XmlRootElement(name = "foos")
@XmlAccessorType(XmlAccessType.NONE)
@XmlType(name = "Foos", propOrder = { "fooList", "foo" })
public class Foos {

    @XmlElement(name="foo")
    protected List<Foo> fooList;

    protected Map<Foo, Foo> foo;

    public Map<Foo, Foo> getFooMap() {
        if (foo == null) {
            foo = new HashMap<Foo, Foo>();
            if (fooList != null)
                for (Foo f : fooList)
                    foo.put(f,  f);
        }
        return this.foo;
    }

    @XmlElement
    public Collection<Foo> getFoo() {
        return getFooMap().values();
    }

}
  • Во время десортировки fooList заполняется данными из <foo>...</foo> элементов xml.

  • Когда getFooMap вызывается в первый раз, он заполняется содержимым fooList (помещая один и тот же объект в качестве ключа и значения).

  • Во время маршалинга вызывается метод getFoo, который возвращает значения карты foo.

person Kjara    schedule 25.09.2018