Примечание: Я EclipseLink JAXB (MOXy) и являюсь членом JAXB 2 (JSR-222) экспертная группа.
Реализация JAXB не требуется использовать класс ObjectFactory
при создании экземпляра объекта.Вы можете настроить создание экземпляра через фабричный класс, используя аннотацию @XmlType
:
@XmlType(factoryClass=ObjectFactory.class, factoryMethod="createImage")
public class Image {
private String filename;
private ImageTypeEnum type;
@XmlElement(name = "imageUri")
public String getAbsoluteUri() {
// some complex computation
return uri;
}
}
Если вы выполните вышеизложенное, то вашРеализация JAXB по-прежнему будет использовать класс Image
для получения метаданных, поэтому она не решит вашу проблему.Альтернативный подход заключается в использовании XmlAdapter
для этого варианта использования:
Еще лучше, если свойство объекта вашего домена не имеетустановщик, вы можете указать вашей реализации JAXB ( EclipseLink MOXy , Metro, Apache JaxMe и т. д.) использовать вместо доступа к полю (переменной экземпляра) @XmlAccessorType(XmlAccessType.FIELD)
:
@XmlAccessorType(XmlAccessType.FIELD)
public class Image {
}
ОБНОВЛЕНИЕ # 1
Если вы не можете изменять доменные объекты, вас могут заинтересовать внешние метаданные MOXy.Это расширение предоставляет средства через XML для предоставления метаданных JAXB для классов, в которых нельзя изменить источник.
Для получения дополнительной информации
ОБНОВЛЕНИЕ № 2 - По результатам чата
Изображение
Ниже приведена реализация Image
класс, который я буду использовать для этого примера.Для сложных вычислений getAbsoluteUri()
я просто добавляю префикс "CDN" к имени файла:
package forum7552310;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
@XmlRootElement(name = "image")
public class Image {
private String filename;
private ImageTypeEnum type;
@XmlElement(name = "imageUri")
public String getAbsoluteUri() {
return "CDN" + filename;
}
}
binding.xml
Ниже приведен связывающий документ MOXy, который я собрал.В этом файле я делаю несколько вещей:
- Установите
XmlAccessorType
на FIELD
- Отметьте свойство absoluteURI равным
XmlTransient
, так как мы будем отображать filename
Вместо этого. - Укажите, что XmlAdapter будет использоваться с полем
filename
.Это делается для применения логики, которая выполняется в методе getAbsoluteUri()
.
<?xml version="1.0"?>
<xml-bindings
xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
package-name="forum7552310">
<java-types>
<java-type name="Image" xml-accessor-type="FIELD">
<java-attributes>
<xml-element java-attribute="filename" name="imageUri">
<xml-java-type-adapter value="forum7552310.FileNameAdapter"/>
</xml-element>
<xml-transient java-attribute="absoluteUri"/>
</java-attributes>
</java-type>
</java-types>
</xml-bindings>
FileNameAdapter
Ниже приведена реализация XmlAdapter
, которая применяет тот же алгоритм имен, что и метод getAbsoluteUri()
:
package forum7552310;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class FileNameAdapter extends XmlAdapter<String, String> {
@Override
public String marshal(String string) throws Exception {
return "CDN" + string;
}
@Override
public String unmarshal(String adaptedString) throws Exception {
return adaptedString.substring(3);
}
}
Демо
Ниже приведен демонстрационный код, демонстрирующий, как применить файл связывания при создании JAXBContext:
package forum7552310;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import org.eclipse.persistence.jaxb.JAXBContextFactory;
public class Demo {
public static void main(String[] args) throws Exception {
Map<String, Object> properties = new HashMap<String, Object>(1);
properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, "forum7552310/binding.xml");
JAXBContext jc = JAXBContext.newInstance(new Class[] {Image.class}, properties);
File xml = new File("src/forum7552310/input.xml");
Unmarshaller unmarshaller = jc.createUnmarshaller();
Image image = (Image) unmarshaller.unmarshal(xml);
System.out.println(image.getAbsoluteUri());
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(image, System.out);
}
}
jaxb.properties
Вам необходимо включить файл с именем jaxb.properties
со следующим содержимым в тот же пакет, что и ваш Image
класс:
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
input.xml
Вот XML-вход, который я использовал:
<?xml version="1.0" encoding="UTF-8"?>
<image>
<imageUri>CDNURI</imageUri>
</image>
Выход
А вот результат запуска демокод:
CDNURI
<?xml version="1.0" encoding="UTF-8"?>
<image>
<imageUri>CDNURI</imageUri>
</image>