Java 基于抽象类值的具体实现更改元素标记
假设我有一个名为Java 基于抽象类值的具体实现更改元素标记,java,xstream,Java,Xstream,假设我有一个名为AbstractItem的抽象类,在另一个类中用作字段。当我使用XStream生成XML时,我希望元素标记基于AbstractItem实例的具体实现 我得到的是: <Test> <item class="Item1" name="name 1" description="description 1"/> </Test> 并使用: stream.aliasType("Item1", Item1.class); 上述两项都不起作用 为清楚
AbstractItem
的抽象类,在另一个类中用作字段。当我使用XStream生成XML时,我希望元素标记基于AbstractItem
实例的具体实现
我得到的是:
<Test>
<item class="Item1" name="name 1" description="description 1"/>
</Test>
并使用:
stream.aliasType("Item1", Item1.class);
上述两项都不起作用
为清楚起见,以下是上述内容的可运行示例: Test.java
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
@XStreamAlias("Test")
public class Test {
public AbstractItem item;
public static void main(String[] args){
Test t1 = new Test();
Item1 item1 = new Item1();
item1.name = "name 1";
item1.description = "description 1";
t1.item = item1;
XStream stream = new XStream();
stream.setMode(XStream.NO_REFERENCES);
stream.autodetectAnnotations(true);
stream.alias("Item1", Item1.class);
System.out.println(stream.toXML(t1));
}
}
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
public abstract class AbstractItem {
@XStreamAsAttribute
public String name;
}
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
public class Item1 extends AbstractItem {
@XStreamAsAttribute
public String description;
}
AbstractItem.java
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
@XStreamAlias("Test")
public class Test {
public AbstractItem item;
public static void main(String[] args){
Test t1 = new Test();
Item1 item1 = new Item1();
item1.name = "name 1";
item1.description = "description 1";
t1.item = item1;
XStream stream = new XStream();
stream.setMode(XStream.NO_REFERENCES);
stream.autodetectAnnotations(true);
stream.alias("Item1", Item1.class);
System.out.println(stream.toXML(t1));
}
}
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
public abstract class AbstractItem {
@XStreamAsAttribute
public String name;
}
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
public class Item1 extends AbstractItem {
@XStreamAsAttribute
public String description;
}
Item1.java
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
@XStreamAlias("Test")
public class Test {
public AbstractItem item;
public static void main(String[] args){
Test t1 = new Test();
Item1 item1 = new Item1();
item1.name = "name 1";
item1.description = "description 1";
t1.item = item1;
XStream stream = new XStream();
stream.setMode(XStream.NO_REFERENCES);
stream.autodetectAnnotations(true);
stream.alias("Item1", Item1.class);
System.out.println(stream.toXML(t1));
}
}
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
public abstract class AbstractItem {
@XStreamAsAttribute
public String name;
}
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
public class Item1 extends AbstractItem {
@XStreamAsAttribute
public String description;
}
更新: 我尝试使用converter类执行此操作,但仍然不正确:
stream.registerConverter(
new Converter(){
@Override
public boolean canConvert(Class type) {
if (AbstractItem.class.isAssignableFrom(type)){
return true;
}
return false;
}
@Override
public void marshal(Object source, HierarchicalStreamWriter writer,
MarshallingContext context) {
AbstractItem item = (AbstractItem)source;
if(source instanceof Item1){
writer.startNode("Item1");
writer.addAttribute("description",((Item1)item).description);
} else if(source instanceof Item2){
writer.startNode("Item2");
writer.addAttribute("description", ((Item2)item).description);
} else {
writer.startNode("Item");
}
writer.addAttribute("name", item.name);
writer.endNode();
}
@Override
public Object unmarshal(HierarchicalStreamReader reader,
UnmarshallingContext context) {
// TODO Auto-generated method stub
AbstractItem item = null;
String nodeName = reader.getNodeName();
if (nodeName.equals("Item1")){
item = new Item1();
((Item1)item).description = reader.getAttribute("description");
} else if (nodeName.equals("Item2")){
item = new Item2();
((Item2)item).description = reader.getAttribute("description");
}
item.name = reader.getAttribute("name");
return item;
}
});
我现在得到的结果是:
<Test>
<item class="Item1">
<Item1 description="description 1" name="name 1"/>
</item>
</Test>
我发现实现这一点的唯一方法是为包含我要为其操作元素标记的对象的类使用自定义转换器。在问题中的示例中,它将是
测试
类的自定义转换器,看起来如下所示:
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
public class BasicConverter implements Converter {
@Override
public boolean canConvert(Class type) {
return Test.class.isAssignableFrom(type);
}
@Override
public void marshal(Object source, HierarchicalStreamWriter writer,
MarshallingContext context) {
if (((Test) source).item instanceof Item1) {
writer.startNode("Item1");
writer.addAttribute("description", ((Item1)((Test) source).item).description);
} else if (((Test) source).item instanceof Item2) {
writer.startNode("Item2");
writer.addAttribute("description", ((Item2)((Test) source).item).description);
}
writer.addAttribute("name", ((Test) source).item.name);
writer.endNode();
}
@Override
public Object unmarshal(HierarchicalStreamReader reader,
UnmarshallingContext context) {
Test test = new Test();
reader.moveDown();
String nodeName = reader.getNodeName();
AbstractItem item = null;
if (nodeName.equals("Item1")) {
item = new Item1();
((Item1)item).description = reader.getAttribute("description");
} else if (nodeName.equals("Item2")) {
item = new Item2();
((Item2)item).description = reader.getAttribute("description");
}
item.name = reader.getAttribute("name");
((Test)test).item = item;
reader.moveUp();
return test;
}
}
这给出了我在上面寻找的输出,但对我来说并不真正令人满意。原因是,我需要使用它的实际类有很多字段,有些字段使用自己的自定义转换器、自定义别名等。此外,它基本上会忽略测试类上的所有注释,除了在类级别定义的注释之外。另外,随着类的增长,您必须更新此转换器以处理这些新字段,否则它们将被包括在内
理想情况下,我想要一个转换器,它可以完成注释定义的所有操作,除了某些字段。目前还没有一个是我知道的。我正在做的是扩展
com.thoughtworks.xstream.converters.reflection.ReflectionConverter
类来实现这一点。但它需要从底层实现中复制更多的代码,这是我特别关心的 我发现实现这一点的唯一方法是为包含我要为其操作元素标记的对象的类使用自定义转换器。在问题中的示例中,它将是测试
类的自定义转换器,看起来如下所示:
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
public class BasicConverter implements Converter {
@Override
public boolean canConvert(Class type) {
return Test.class.isAssignableFrom(type);
}
@Override
public void marshal(Object source, HierarchicalStreamWriter writer,
MarshallingContext context) {
if (((Test) source).item instanceof Item1) {
writer.startNode("Item1");
writer.addAttribute("description", ((Item1)((Test) source).item).description);
} else if (((Test) source).item instanceof Item2) {
writer.startNode("Item2");
writer.addAttribute("description", ((Item2)((Test) source).item).description);
}
writer.addAttribute("name", ((Test) source).item.name);
writer.endNode();
}
@Override
public Object unmarshal(HierarchicalStreamReader reader,
UnmarshallingContext context) {
Test test = new Test();
reader.moveDown();
String nodeName = reader.getNodeName();
AbstractItem item = null;
if (nodeName.equals("Item1")) {
item = new Item1();
((Item1)item).description = reader.getAttribute("description");
} else if (nodeName.equals("Item2")) {
item = new Item2();
((Item2)item).description = reader.getAttribute("description");
}
item.name = reader.getAttribute("name");
((Test)test).item = item;
reader.moveUp();
return test;
}
}
这给出了我在上面寻找的输出,但对我来说并不真正令人满意。原因是,我需要使用它的实际类有很多字段,有些字段使用自己的自定义转换器、自定义别名等。此外,它基本上会忽略测试类上的所有注释,除了在类级别定义的注释之外。另外,随着类的增长,您必须更新此转换器以处理这些新字段,否则它们将被包括在内
理想情况下,我想要一个转换器,它可以完成注释定义的所有操作,除了某些字段。目前还没有一个是我知道的。我正在做的是扩展
com.thoughtworks.xstream.converters.reflection.ReflectionConverter
类来实现这一点。但它需要从底层实现中复制更多的代码,这是我特别关心的 我在使用XStream时也面临同样的问题。我以前使用过使用反射读取xml的方法。这将为您提供读取xml时所需的功能。缺点是它无法编写xml。
我更喜欢digester,因为它不需要更改java类中的任何内容(没有注释或转换器内容),而且设置解析xml的规则也很容易。但它并没有从XStream或Jaxb获得的所有功能。
现在我必须使用XStream(或Jaxb)解决这个问题,所以我想我必须编写所需的转换器材料。谢谢你的例子。我在XStream上也面临同样的问题。我以前使用过使用反射读取xml的方法。这将为您提供读取xml时所需的功能。缺点是它无法编写xml。 我更喜欢digester,因为它不需要更改java类中的任何内容(没有注释或转换器内容),而且设置解析xml的规则也很容易。但它并没有从XStream或Jaxb获得的所有功能。
现在我必须使用XStream(或Jaxb)解决这个问题,所以我想我必须编写所需的转换器材料。谢谢你的例子。我开始怀疑这是否可能?我开始怀疑这是否可能?