【发布时间】:2014-12-03 03:18:17
【问题描述】:
用例:
我们设计了一个基于 JOOQ 的调制框架,它是 SQL 的 DSL。每个模块都会有一个 API 子模块和 IMPL 子模块。在 API 级别,对于每个 ReadOnly 访问,我们只公开一个特定的“视图”接口以避免带来混淆,其中仅包含 getter。
为了桥接模型和只读视图,我们使用 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
只读视图界面:
@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 {}
豆类:
@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 试过了,还是一样的问题。
【问题讨论】:
标签: json eclipselink moxy