JAXB переопределить тип списка @XmlElement
Там простой класс Bean1
с подсписком типа BeanChild1
,
@XmlRootElement(name="bean")
@XmlAccessorType(XmlAccessType.PROPERTY)
public static class Bean1
{
public Bean1()
{
super();
}
private List<BeanChild1> childList = new ArrayList<>();
@XmlElement(name="child")
public List<BeanChild1> getChildList()
{
return childList;
}
public void setChildList(List<BeanChild1> pChildList)
{
childList = pChildList;
}
}
public static class BeanChild1 { ... }
Я пытаюсь переопределить класс, чтобы изменить тип списка. Новый дочерний класс (т.е. BeanChild2
) расширяет предыдущий (т.е. BeanChild1
)
public static class Bean2 extends Bean1
{
public Bean2()
{
super();
}
@Override
@XmlElement(name="child", type=BeanChild2.class)
public List<BeanChild1> getChildList()
{
return super.getChildList();
}
}
public static class BeanChild2 extends BeanChild1 { }
Итак, вот как я это проверил:
public static void main(String[] args)
{
String xml = "<bean>" +
" <child></child>" +
" <child></child>" +
" <child></child>" +
"</bean>";
Reader reader = new StringReader(xml);
Bean2 b2 = JAXB.unmarshal(reader, Bean2.class);
assert b2.getChildList().get(0) instanceof BeanChild2; // fails
}
Тест показывает, что этот список все еще содержит потомков BeanChild1
,
Итак, как я могу заставить его заполнить childList
поле с BeanChild2
случаи?
Если нет простых решений, не стесняйтесь размещать более креативные решения (например, используя XmlAdapter
s, Unmarshaller.Listener
Возможно, дополнительная аннотация на родительский или дочерний класс...)
1 ответ
Нет способа изменить (например, переопределить) @XmlElement
аннотация суперкласса. По крайней мере, не используя аннотации.
- Не важно что
@XmlAccessorType
вы используете (например,FIELD
,PROPERTY
,PUBLIC
,NONE
). - Это не имеет никакого значения, если вы размещаете аннотации на полях или на получателях.
Однако есть разумная альтернатива. Реализация JAXB для MOXy предлагает возможность определять метаданные / привязки в файле XML. Фактически, у каждой java-аннотации есть альтернатива XML. Но это становится лучше: вы можете комбинировать как Java-аннотации, так и XML-метаданные. Круто то, что MOXy объединит оба объявления, и в случае конфликта метаданные, определенные в XML, получат более высокий приоритет.
Предполагая, что Bean1
класс аннотирован, как указано выше. Затем можно переопределить привязку в файле XML. например:
<xml-bindings xml-accessor-type="PROPERTY">
<java-types>
<java-type name="Bean1">
<xml-element java-attribute="childList" name="child"
type="BeanChild2" container-type="java.util.ArrayList" />
</java-type>
</java-types>
</xml-bindings>
Этот новый файл привязок необходим при создании объекта контекста.
// use a map to reference the xml file
Map<String, Object> propertyMap = new HashMap<>();
propertyMap.put(JAXBContextProperties.OXM_METADATA_SOURCE, "bindings.xml");
// pass this properyMap during the creation of the JAXB context.
JAXBContext context = JAXBContext.newInstance(..., propertyMap);
MOXy объединит Java-аннотации и XML-привязки, и в случае конфликта применяются определенные XML-параметры. В этом случае, чем раньше @XmlElement(name=child)
аннотация заменяется определением XML, которое эквивалентно @XmlElement(name=child, type=BeanChild2.class)
,
Вы можете прочитать больше о привязках XML здесь.