我了解所有关于如何使用
XMLAdapters到
convert unmappable types,或者只是改变某些对象如何序列化/反序列化为XML.如果我使用注释(包级别或其他方式),一切都会很好.问题是我正在尝试更改第三方对象的表示,我不能将源代码更改为(即为了注入注释).
这不应该是一个问题,考虑到Marshaller对象有一个方法manually adding adapters.不幸的是,无论我做什么,我不能得到这样的方式设置为“踢”.例如,我有一个类代表XYZ空间中的一个点(地心坐标).在我生产的XML中,我希望将其转换为lat / long / altitude(大地坐标).这是我的课程:
地心
- package testJaxb;
- import javax.xml.bind.annotation.XmlAttribute;
- import javax.xml.bind.annotation.XmlRootElement;
- @XmlRootElement
- public class GeocentricCoordinate {
- // Units are in meters; see http://en.wikipedia.org/wiki/Geocentric_coordinates
- private double x;
- private double y;
- private double z;
- @XmlAttribute
- public double getX() {
- return x;
- }
- public void setX(double x) {
- this.x = x;
- }
- @XmlAttribute
- public double getY() {
- return y;
- }
- public void setY(double y) {
- this.y = y;
- }
- @XmlAttribute
- public double getZ() {
- return z;
- }
- public void setZ(double z) {
- this.z = z;
- }
- }
大地
- package testJaxb;
- import javax.xml.bind.annotation.XmlAttribute;
- import javax.xml.bind.annotation.XmlRootElement;
- /**
- * @see http://en.wikipedia.org/wiki/Geodetic_system
- */
- @XmlRootElement
- public class GeodeticCoordinate {
- private double latitude;
- private double longitude;
- // Meters
- private double altitude;
- public GeodeticCoordinate() {
- this(0,0);
- }
- public GeodeticCoordinate(double latitude,double longitude,double altitude) {
- super();
- this.latitude = latitude;
- this.longitude = longitude;
- this.altitude = altitude;
- }
- @XmlAttribute
- public double getLatitude() {
- return latitude;
- }
- public void setLatitude(double latitude) {
- this.latitude = latitude;
- }
- @XmlAttribute
- public double getLongitude() {
- return longitude;
- }
- public void setLongitude(double longitude) {
- this.longitude = longitude;
- }
- @XmlAttribute
- public double getAltitude() {
- return altitude;
- }
- public void setAltitude(double altitude) {
- this.altitude = altitude;
- }
- }
GeocentricToGeodeticLocationAdapter
- package testJaxb;
- import javax.xml.bind.JAXBContext;
- import javax.xml.bind.JAXBException;
- import javax.xml.bind.Marshaller;
- import javax.xml.bind.annotation.adapters.XmlAdapter;
- /**
- * One of our systems uses xyz coordinates to represent locations. Consumers of our XML would much
- * prefer lat/lon/altitude. This handles converting between xyz and lat lon alt.
- *
- * @author ndunn
- *
- */
- public class GeocentricToGeodeticLocationAdapter extends XmlAdapter<GeodeticCoordinate,GeocentricCoordinate> {
- @Override
- public GeodeticCoordinate marshal(GeocentricCoordinate arg0) throws Exception {
- // TODO: do a real coordinate transformation
- GeodeticCoordinate coordinate = new GeodeticCoordinate();
- coordinate.setLatitude(45);
- coordinate.setLongitude(45);
- coordinate.setAltitude(1000);
- return coordinate;
- }
- @Override
- public GeocentricCoordinate unmarshal(GeodeticCoordinate arg0) throws Exception {
- // TODO do a real coordinate transformation
- GeocentricCoordinate gcc = new GeocentricCoordinate();
- gcc.setX(100);
- gcc.setY(200);
- gcc.setZ(300);
- return gcc;
- }
- }
ObjectWithLocation字段
- package testJaxb;
- import javax.xml.bind.JAXBContext;
- import javax.xml.bind.JAXBException;
- import javax.xml.bind.Marshaller;
- import javax.xml.bind.annotation.XmlRootElement;
- @XmlRootElement
- public class ObjectWithLocation {
- private GeocentricCoordinate location = new GeocentricCoordinate();
- public GeocentricCoordinate getLocation() {
- return location;
- }
- public void setLocation(GeocentricCoordinate location) {
- this.location = location;
- }
- public static void main(String[] args) {
- ObjectWithLocation object = new ObjectWithLocation();
- try {
- JAXBContext context = JAXBContext.newInstance(ObjectWithLocation.class,GeodeticCoordinate.class,GeocentricCoordinate.class);
- Marshaller marshaller = context.createMarshaller();
- marshaller.setAdapter(new GeocentricToGeodeticLocationAdapter());
- marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,true);
- marshaller.marshal(object,System.out);
- }
- catch (JAXBException jaxb) {
- jaxb.printStackTrace();
- }
- }
- }
输出:
- <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
- <objectWithLocation>
- <location z="0.0" y="0.0" x="0.0"/>
- </objectWithLocation>
通过使用注释(在我的package-info.java文件中):
- @javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters
- ({
- @javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter(value=GeocentricToGeodeticLocationAdapter.class,type=GeocentricCoordinate.class),})
- package package testJaxb;
我得到以下(所需)xml
- <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
- <objectWithLocation>
- <location longitude="45.0" latitude="45.0" altitude="1000.0"/>
- </objectWithLocation>
所以我的问题是双重的.
>为什么适配器在注释时工作,但是通过setAdapter方法显式设置时不适用?
>如果我有类不能注释的类,并且我的package-info.java我不能修改以添加注释,我该如何解决这个问题?
解决方法
Marshaller上的setAdapter(XmlAdapter)用于传递已经使用@XmlJavaTypeAdapter注释的属性的初始化XmlAdapter.下面的链接是一个我利用这个行为的答案:
> Using JAXB to cross reference XmlIDs from two XML files
如果你想映射第三方类,你可以使用EclipseLink JAXB (MOXy)的XML映射文件(我是MOXy的主管):
> @L_301_5@