适用于JAXB的通用适配器

Vol*_*dyi 3 java xml jaxb xjc moxy

假设我有班级人物:

class Person{
  String firstName;
  String lastName;
  String email;
}
Run Code Online (Sandbox Code Playgroud)

XML具有以下格式:

<person>
 <firstName value="asd" /> 
 <lastName value="bcd" />
 <email value="qwe" />
</person>
Run Code Online (Sandbox Code Playgroud)

我可以为每个字段FirstNameAdapter,LastNameAdapter,EmailAdapter使用自己的XmlAdapter实现解组/编组此类.正如您所看到的,每个字段以类似的方式表示 - 字段名称为xml元素,字段值为元素属性.是否有可能创建"通用"适配器,我将能够转移该字段的名称,它将提取该字段的值?

PS我知道MOXy JAXB实现,但我想知道是否可以通过引用JAXB实现.

谢谢!

MvG*_*MvG 5

你可以使用XmlAdapter这样的:

import java.io.*;
import javax.xml.bind.*;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.*;

@XmlType
class Valued {
    @XmlAttribute(name="value")
    public String value;
}

class ValuedAdapter extends XmlAdapter<Valued, String> {
    public Valued marshal(String s) {
        Valued v = new Valued();
        v.value = s;
        return v;
    }
    public String unmarshal(Valued v) {
        return v.value;
    }
}

@XmlRootElement
class Person {

    @XmlJavaTypeAdapter(ValuedAdapter.class)
    @XmlElement
    String firstName;

    @XmlJavaTypeAdapter(ValuedAdapter.class)
    @XmlElement
    String lastName;

}

class SO12928971 {
    public static void main(String[] args) throws Exception {
        Person p = new Person();
        p.firstName = "John";
        p.lastName = "Doe";
        JAXBContext jc = JAXBContext.newInstance(Person.class);
        StringWriter sw = new StringWriter();
        jc.createMarshaller().marshal(p, sw);
        String xml = sw.toString();
        System.out.println(xml);
        StringReader sr = new StringReader(xml);
        p = (Person)jc.createUnmarshaller().unmarshal(sr);
        assert "John".equals(p.firstName);
        assert "Doe".equals(p.lastName);
    }
}
Run Code Online (Sandbox Code Playgroud)

这里的想法是XML Schema,因此JAXB在元素名称内容类型之间有明确的区别,即使许多文档在这两者之间有明确的一对一对应关系.所以在上面的代码中,类型 Valued描述了具有value属性的东西,而不考虑元素名称.要序列化的成员将注释为该注释中@XmlElement不包含任何名称.因此,他们将生成具有从成员名称派生的名称的元素.该@XmlJavaTypeAdapter注释将导致串行仿佛它们的类型维尔对待这些成员Valued.这就是他们的XML内容类型.

上面代码的架构如下所示:

<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:element name="person" type="person"/>

  <xs:complexType name="person">
    <xs:sequence>
      <xs:element name="firstName" type="valued" minOccurs="0"/>
      <xs:element name="lastName" type="valued" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="valued">
    <xs:sequence/>
    <xs:attribute name="value" type="xs:string"/>
  </xs:complexType>
</xs:schema>
Run Code Online (Sandbox Code Playgroud)