如何使用XStream处理不同的孩子?

时间:2012-11-15 20:21:25

标签: java xml xstream

这是情景:

<family>
    <person>name</person>
    <person>
        <address> street </adress>
        <address> street </address>
    </person>
</family>

人员值可以是地址列表,也可以是人名。 我认为解决方案是使用转换器,但你是如何做到的?

  1. 检查您检索的输入是什么?
  2. 告诉转换器继续使用类3的默认值?
  3. 示例类:(请注意,这只是为了说明)

    public class Person {
    
        private String name;
    
        private List<Address> address;
    }
    
    public class Address {
        private String street;    
    }
    

1 个答案:

答案 0 :(得分:2)

您确实需要使用转换器。以下是您的示例转换器:

public class PersonConverter implements Converter {

    public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext context) {
        Person person = (Person) value;
        if(person.name != null){
            writer.setValue(person.name);
        } else if(person.address != null){
            for (Address address : person.address){
                writer.startNode("address");
                writer.setValue(address.street);
                writer.endNode();
            }
        }


    }

    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
        Person person = new Person();
        person.name = reader.getValue();
        if(person.name.trim().length()==0){
            person.name = null;
        }
        List<Address> addresses = getAddress(reader, new ArrayList<Address>());
        person.address = addresses;
        if(person.address.size() == 0){
            person.address = null;
        }
        return person;
    }

    private List<Address> getAddress(HierarchicalStreamReader reader, List<Address> addresses){
        if (!reader.hasMoreChildren()){
            return addresses;
        }
        reader.moveDown();
        if(reader.getNodeName().equals("address")){
            addresses.add(new Address(reader.getValue()));
            reader.moveUp();
            getAddress(reader, addresses);
        }
        return addresses;
    }

    public boolean canConvert(Class clazz) {
        return clazz.equals(Person.class);
    }
}

这是主要方法:

public static void main(String[] args) {        
    List<Person> persons = new ArrayList<Person>();
    persons.add(new Person("John"));

    List<Address> adds = new ArrayList<Address>();
    adds.add(new Address("123 street"));
    adds.add(new Address("456 street"));

    persons.add(new Person(adds));

    Family family = new Family(persons);


    XStream stream = new XStream();     
    stream.registerConverter(new PersonConverter());
    stream.processAnnotations(new Class[]{Family.class});

    String xml = stream.toXML(family);
    System.out.println(xml);

    Family testFam = (Family) stream.fromXML(xml);
    System.out.println("family.equals(testFam) => "+family.equals(testFam));

}

如果为FamilyPersonAddress类实现equals方法,则应该在运行时打印它们在方法结束时相等。另外值得注意的是,我在Family上使用了一些注释。我在类本身上使用了@XStreamAlias("family"),然后在我使用Person的{​​{1}}个对象的集合上使用了。{/ p>

当我运行提供的主要方法时,这是我的输出:

@XStreamImplicit(itemFieldName="person")