用例:
我们设计了一个基于JOOQ的调制框架,这是一个用于SQL的DSL。每个模块都有一个API子模块和IMPL子模块。在API级别,对于每个ReadOnly访问,我们只公开一个特定的“视图”界面,以避免产生混淆,其中只包含getter。
要桥接模型和ReadOnly View,我们使用java Proxy。
因此会有一些高级接口,具体级别可以扩展。然后我们遇到了错误:
Exception in thread "main" javax.xml.bind.JAXBException:
Exception Description: The java interface example.json.demo2.IAddress can not be mapped by JAXB as it has multiple mappable parent interfaces. Multiple inheritence is not supported
- with linked exception:
[Exception [EclipseLink-50089] (Eclipse Persistence Services - 2.6.0.v20140809-296a69f): org.eclipse.persistence.exceptions.JAXBException
Exception Description: The java interface example.json.demo2.IAddress can not be mapped by JAXB as it has multiple mappable parent interfaces. Multiple inheritence is not supported]
at org.eclipse.persistence.jaxb.JAXBContext$TypeMappingInfoInput.createContextState(JAXBContext.java:1108)
at org.eclipse.persistence.jaxb.JAXBContext.<init>(JAXBContext.java:188)
at org.eclipse.persistence.jaxb.JAXBContextFactory.createContext(JAXBContextFactory.java:165)
at org.eclipse.persistence.jaxb.JAXBContextFactory.createContext(JAXBContextFactory.java:152)
at org.eclipse.persistence.jaxb.JAXBContextFactory.createContext(JAXBContextFactory.java:112)
at org.eclipse.persistence.jaxb.JAXBContextFactory.createContext(JAXBContextFactory.java:102)
at example.json.demo2.Demo.main(Demo.java:26)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Caused by: Exception [EclipseLink-50089] (Eclipse Persistence Services - 2.6.0.v20140809-296a69f): org.eclipse.persistence.exceptions.JAXBException
Exception Description: The java interface example.json.demo2.IAddress can not be mapped by JAXB as it has multiple mappable parent interfaces. Multiple inheritence is not supported
at org.eclipse.persistence.exceptions.JAXBException.invalidInterface(JAXBException.java:1116)
at org.eclipse.persistence.jaxb.javamodel.reflection.JavaClassImpl.getSuperclass(JavaClassImpl.java:360)
at org.eclipse.persistence.jaxb.compiler.AnnotationsProcessor.postProcessXmlAccessorType(AnnotationsProcessor.java:1626)
at org.eclipse.persistence.jaxb.compiler.AnnotationsProcessor.buildTypeInfo(AnnotationsProcessor.java:844)
at org.eclipse.persistence.jaxb.compiler.AnnotationsProcessor.postBuildTypeInfo(AnnotationsProcessor.java:773)
at org.eclipse.persistence.jaxb.compiler.AnnotationsProcessor.processClassesAndProperties(AnnotationsProcessor.java:298)
at org.eclipse.persistence.jaxb.compiler.Generator.<init>(Generator.java:156)
at org.eclipse.persistence.jaxb.JAXBContext$TypeMappingInfoInput.createContextState(JAXBContext.java:1104)
... 11 more
ReadOnly View Interface:
@XmlRootElement
public interface IAddress extends A, B {
@XmlPath("/address/@streetAddress")
String getStreet();
void setStreet(String street);
@XmlPath("/address/city/@cityName")
String getCity();
void setCity(String city);
@XmlPath("/address/state/@stateCode")
String getState();
void setState(String state);
@XmlPath("/address/country/@countryCode")
String getCountry();
void setCountry(String country);
@XmlPath("/address/@postalCode")
String getPostalCode();
void setPostalCode(String postalCode);
}
两个超级界面:
public interface A {}
public interface B {}
Bean类:
@XmlType(propOrder = { "country", "state", "city", "street", "postalCode" })
public class Address implements IAddress {
@XmlPath("Placemark/ns:AddressDetails/ns:Country/ns:AdministrativeArea/ns:Locality/ns:Thoroughfare/ns:ThoroughfareName/text()")
private String street;
@XmlPath("Placemark/ns:AddressDetails/ns:Country/ns:AdministrativeArea/ns:Locality/ns:LocalityName/text()")
private String city;
@XmlPath("Placemark/ns:AddressDetails/ns:Country/ns:AdministrativeArea/ns:AdministrativeAreaName/text()")
private String state;
@XmlPath("Placemark/ns:AddressDetails/ns:Country/ns:CountryNameCode/text()")
private String country;
@XmlPath("Placemark/ns:AddressDetails/ns:Country/ns:AdministrativeArea/ns:Locality/ns:PostalCode/ns:PostalCodeNumber/text()")
private String postalCode;
@Override
public String getStreet() {
return street;
}
@Override
public void setStreet(String street) {
this.street = street;
}
@Override
public String getCity() {
return city;
}
@Override
public void setCity(String city) {
this.city = city;
}
@Override
public String getState() {
return state;
}
@Override
public void setState(String state) {
this.state = state;
}
@Override
public String getCountry() {
return country;
}
@Override
public void setCountry(String country) {
this.country = country;
}
@Override
public String getPostalCode() {
return postalCode;
}
@Override
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
}
亚军类:
public class Demo {
public static void main(String[] args) throws Exception {
final FileReader xmlURL = new FileReader("src/main/java/example/json/demo2/response.xml");
final FileReader jsonURL = new FileReader("src/main/java/example/json/demo2/response.json");
JAXBContext jc = JAXBContextFactory.createContext(new Class[]{Address.class, IAddress.class}, new HashMap());
Unmarshaller unmarshaller = jc.createUnmarshaller();
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
// XML
XMLInputFactory xif = XMLInputFactory.newInstance();
StreamSource xml = new StreamSource(xmlURL);
XMLStreamReader xsr = xif.createXMLStreamReader(xml);
xsr.nextTag(); // Advance to kml tag
xsr.nextTag(); // Advance to Response tag
JAXBElement<Address> addressFromXML = unmarshaller.unmarshal(xsr, Address.class);
marshaller.marshal(addressFromXML, System.out);
// JSON
unmarshaller.setProperty("eclipselink.media-type", "application/json");
unmarshaller.setProperty("eclipselink.json.include-root", false);
StreamSource json = new StreamSource(jsonURL);
final JAXBElement<Address> addressFromJSON = unmarshaller.unmarshal(json, Address.class);
marshaller.setProperty("eclipselink.media-type", "application/json");
marshaller.setProperty("eclipselink.json.include-root", false);
final IAddress value = (IAddress) Proxy.newProxyInstance(Demo.class.getClassLoader(), new Class[]{IAddress.class}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
final Address address = addressFromJSON.getValue();
return method.invoke(address, args);
}
});
marshaller.marshal(value, System.out);
}
}
顺便说一句,如果我评论为:
public interface IAddress {//extends A, B {
然后我可以得到:
{
"address" : {
"postalCode" : "94043",
"streetAddress" : "1600 Amphitheatre Pkwy",
"city" : {
"cityName" : "Mountain View"
},
"country" : {
"countryCode" : "US"
},
"state" : {
"stateCode" : "CA"
}
}
}
我尝试使用MOXy 2.6.0-M3,它仍然存在同样的问题。
答案 0 :(得分:0)
以下是答案应该是什么,但它们似乎是一些妨碍它工作的问题:
IAddress
您可以使用MOXy的外部映射文档来指定IAddress
的超级类型java.lang.Object
,或A
或B
中的一个,而不是{{1} }和A
。
B
这种重写适用于类,但MOXy在接口上使用时似乎有问题,请参阅以下问题:
<?xml version="1.0"?>
<xml-bindings
xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
package-name="example.json.demo2">
<java-types>
<java-type name="IAddress" super-type="java.lang.Object"/>
</java-types>
</xml-bindings>
&amp;继承层次结构中的A
或者,您可以使用B
从继承层次结构中删除xml-transient
和A
(请参阅:http://blog.bdoughan.com/2011/06/ignoring-inheritance-with-xmltransient.html)。
B
这种重写适用于类,但MOXy在接口上使用时似乎有问题,请参阅以下问题:
创建<?xml version="1.0"?>
<xml-bindings
xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
package-name="example.json.demo2">
<java-types>
<java-type name="A" xml-transient="true"/>
<java-type name="B" xml-transient="true"/>
</java-types>
</xml-bindings>
时应用映射文件,如下所示:
JAXBContext