如何将简单 Java class 的字段名称映射到名称-值对序列
How to map simple Java class's field names into sequence of name-value pairs
我有一个非常简单的 class,我想将其作为 XML 传输。接受的 XML 格式是由名称属性和字符串值序列组成的字段列表。我可以注释我的 class 以便我可以:
- 使用 class 名称作为 xml 实体
的属性 "type"
- 在 xml 字段序列中使用 class 字段名称作为属性 "name" ?
推荐的方法是什么?有问题的示例 class:
class MyEntityType {
public List<String> myField1; // = {"A", "B"}
public List<String> myField2; // = {"C", "D"}
}
xml格式:
<Entity type="MyEntityType">
<Fields>
<Field name="myField1">
<Value>A</Value>
<Value>B</Value
</Field>
<Field name="myField2">
<Value>C</Value>
<Value>D</Value>
</Field>
</Fields>
</Entity>
我想避免的是必须声明一个字段 class,并将它们的列表放在我的对象中,因为我想强制执行一组特定的必填字段。
class MyEntityType {
public static class Field {
String name;
String values
}
public List<Fields> fields;
}
为完整起见,这些是受支持的架构:
<xs:complexType name="EntityComplexType" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:sequence>
<xs:element name="Fields" type="FieldsComplexType" />
</xs:sequence>
<xs:attribute name="Type" type="xs:string" use="required" />
</xs:complexType>
<xs:complexType name="FieldsComplexType" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:sequence>
<xs:element name="Field" type="FieldComplexType" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="FieldComplexType" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:sequence>
<xs:element name="Value" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="Alias" type="xs:string" use="optional" />
<xs:attribute name="ReferenceValue" type="xs:string" use="optional" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="Name" use="required" />
</xs:complexType>
我想你意识到你想要的是与 XML 的标准程序的重大偏差,忽略了这种数据格式设计的基本概念,以及 Java [的架构] =31=] 绑定也是如此。因此,class 字段意味着由元素名称表示。此外,使用不反映数据结构的 XML 结构 (class MyEntityType),反之亦然,使用与数据结构不对应的 class 会创建开箱即用的工具无法处理的差距。既没有注释也没有外部绑定来实现这个完全不同的结构。
当然有适配器的 JAXB 功能,它有助于将一种 Java 类型替换为另一种类型,但这里必须替换整个 Java 结构才能编组进入 XML.
您的 XML 架构(稍作修改)生成所需的 Java classes EntityComplexType、FieldsComplexType 和 FieldComplexType(我没有在此处粘贴)。
A Java class EntityAdapter 可以写成适配器的精神:
public class EntityAdapter {
public MyEntityType unmarshal(EntityComplexType v){
// ...
return new MyEntityType();
}
public EntityComplexType marshal(MyEntityType v){
EntityComplexType ect = new EntityComplexType();
ect.setType( v.getClass().getSimpleName() );
FieldsComplexType fct = new FieldsComplexType();
ect.setFields( fct );
FieldComplexType field1 = new FieldComplexType();
fct.getField().add( field1 );
field1.setName( "myField1" );
for( String s: v.getMyField1() ){
field1.getValue().add( s );
}
FieldComplexType field2 = new FieldComplexType();
fct.getField().add( field2 );
field2.setName( "myField2" );
for( String s: v.getMyField2() ){
field2.getValue().add( s );
}
return ect;
}
}
编组像往常一样进行,除了将 MyEntityType 对象转换为 EntityComplexType 对象:
MyEntityType met = ...;
EntityAdapter adapter = new EntityAdapter();
EntityComplexType ect = adapter.marshal( met );
ObjectFactory of = new ObjectFactory();
JAXBElement<EntityComplexType> jbe = of.createEntityComplexType( ect );
JAXBContext jc = JAXBContext.newInstance( PACKAGE );
Marshaller m = jc.createMarshaller();
m.marshal( jbe, ... );
我有一个非常简单的 class,我想将其作为 XML 传输。接受的 XML 格式是由名称属性和字符串值序列组成的字段列表。我可以注释我的 class 以便我可以:
- 使用 class 名称作为 xml 实体 的属性 "type"
- 在 xml 字段序列中使用 class 字段名称作为属性 "name" ?
推荐的方法是什么?有问题的示例 class:
class MyEntityType {
public List<String> myField1; // = {"A", "B"}
public List<String> myField2; // = {"C", "D"}
}
xml格式:
<Entity type="MyEntityType">
<Fields>
<Field name="myField1">
<Value>A</Value>
<Value>B</Value
</Field>
<Field name="myField2">
<Value>C</Value>
<Value>D</Value>
</Field>
</Fields>
</Entity>
我想避免的是必须声明一个字段 class,并将它们的列表放在我的对象中,因为我想强制执行一组特定的必填字段。
class MyEntityType {
public static class Field {
String name;
String values
}
public List<Fields> fields;
}
为完整起见,这些是受支持的架构:
<xs:complexType name="EntityComplexType" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:sequence>
<xs:element name="Fields" type="FieldsComplexType" />
</xs:sequence>
<xs:attribute name="Type" type="xs:string" use="required" />
</xs:complexType>
<xs:complexType name="FieldsComplexType" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:sequence>
<xs:element name="Field" type="FieldComplexType" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="FieldComplexType" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:sequence>
<xs:element name="Value" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="Alias" type="xs:string" use="optional" />
<xs:attribute name="ReferenceValue" type="xs:string" use="optional" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="Name" use="required" />
</xs:complexType>
我想你意识到你想要的是与 XML 的标准程序的重大偏差,忽略了这种数据格式设计的基本概念,以及 Java [的架构] =31=] 绑定也是如此。因此,class 字段意味着由元素名称表示。此外,使用不反映数据结构的 XML 结构 (class MyEntityType),反之亦然,使用与数据结构不对应的 class 会创建开箱即用的工具无法处理的差距。既没有注释也没有外部绑定来实现这个完全不同的结构。
当然有适配器的 JAXB 功能,它有助于将一种 Java 类型替换为另一种类型,但这里必须替换整个 Java 结构才能编组进入 XML.
您的 XML 架构(稍作修改)生成所需的 Java classes EntityComplexType、FieldsComplexType 和 FieldComplexType(我没有在此处粘贴)。
A Java class EntityAdapter 可以写成适配器的精神:
public class EntityAdapter {
public MyEntityType unmarshal(EntityComplexType v){
// ...
return new MyEntityType();
}
public EntityComplexType marshal(MyEntityType v){
EntityComplexType ect = new EntityComplexType();
ect.setType( v.getClass().getSimpleName() );
FieldsComplexType fct = new FieldsComplexType();
ect.setFields( fct );
FieldComplexType field1 = new FieldComplexType();
fct.getField().add( field1 );
field1.setName( "myField1" );
for( String s: v.getMyField1() ){
field1.getValue().add( s );
}
FieldComplexType field2 = new FieldComplexType();
fct.getField().add( field2 );
field2.setName( "myField2" );
for( String s: v.getMyField2() ){
field2.getValue().add( s );
}
return ect;
}
}
编组像往常一样进行,除了将 MyEntityType 对象转换为 EntityComplexType 对象:
MyEntityType met = ...;
EntityAdapter adapter = new EntityAdapter();
EntityComplexType ect = adapter.marshal( met );
ObjectFactory of = new ObjectFactory();
JAXBElement<EntityComplexType> jbe = of.createEntityComplexType( ect );
JAXBContext jc = JAXBContext.newInstance( PACKAGE );
Marshaller m = jc.createMarshaller();
m.marshal( jbe, ... );