Sam*_*Sam 1 jaxb xjc unmarshalling
我有一个响应 xml 数据的 Web 服务器和一个使用它的客户端。两者共享相同的域代码。域对象之一如下所示:
@XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
@XmlRootElement(name = "image")
public class Image {
private String filename;
private ImageTypeEnum type;
@XmlElement(name = "imageUri")
public String getAbsoluteUri() {
// some complex computation
return uri;
}
}
Run Code Online (Sandbox Code Playgroud)
当我尝试将来自服务器的响应解组到这个对象中时,由于没有绝对 Uri 的设置器,我在类中没有 imageUri。所以我像这样扩展它:
public class FEImage extends Image{
private String imageUri;
public String getAbsoluteUri() {
return imageUri;
}
public void setAbsoluteUri(String imageUri) {
this.imageUri = imageUri;
}
}
Run Code Online (Sandbox Code Playgroud)
我的对象工厂
@XmlRegistry
public class ObjectFactory {
public Image createImage(){
return new FEImage();
}
}
Run Code Online (Sandbox Code Playgroud)
我的解组代码在这里:
JAXBContext context = JAXBContext.newInstance(ObjectFactory.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
unmarshaller.setProperty("com.sun.xml.bind.ObjectFactory",new ObjectFactory());
((JAXBElement)unmarshaller.unmarshal((InputStream) response.getEntity())).getValue();
Run Code Online (Sandbox Code Playgroud)
但是,setAbsoluteUri在FEImage解组时似乎没有被调用。当我在 中添加一个虚拟对象setAbsoluteUri时Image.java,一切都按预期进行。
有人能告诉我如何干净地从 扩展Image.java吗?
注意: 我是EclipseLink JAXB (MOXy) 的负责人和JAXB 2 (JSR-222)专家组的成员。
ObjectFactory实例化对象时,JAXB 实现不需要使用该类。您可以使用@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;
}
}
Run Code Online (Sandbox Code Playgroud)
如果您执行上述操作,那么您的 JAXB 实现仍将使用Image该类来派生元数据,因此它不会解决您的问题。另一种方法是在XmlAdapter此用例中使用 :
更好的是,当域对象上的属性没有 setter 时,您可以告诉 JAXB 实现(EclipseLink MOXy、Metro、Apache JaxMe 等)使用字段(实例变量)访问,而不是使用@XmlAccessorType(XmlAccessType.FIELD):
@XmlAccessorType(XmlAccessType.FIELD)
public class Image {
}
Run Code Online (Sandbox Code Playgroud)
更新 #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;
}
}
Run Code Online (Sandbox Code Playgroud)
绑定文件
下面是我放在一起的 MOXy 绑定文件。在这个文件中,我做了几件事:
XmlAccessorType为FIELDXmlTransient因为我们将filename改为映射该字段。filename字段一起使用的 XmlAdapter 。这是为了应用在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>
Run Code Online (Sandbox Code Playgroud)
文件名适配器
下面是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);
}
}
Run Code Online (Sandbox Code Playgroud)
演示
下面是演示如何在创建 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);
}
}
Run Code Online (Sandbox Code Playgroud)
jaxb.properties
您需要jaxb.properties在与您的Image类相同的包中包含一个以以下内容命名的文件:
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
Run Code Online (Sandbox Code Playgroud)
输入文件
这是我使用的 XML 输入:
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
Run Code Online (Sandbox Code Playgroud)
输出
这是运行演示代码的输出:
CDNURI
<?xml version="1.0" encoding="UTF-8"?>
<image>
<imageUri>CDNURI</imageUri>
</image>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10011 次 |
| 最近记录: |