使用 xstream 自定义 java 集合的序列化

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1791178/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 17:59:55  来源:igfitidea点击:

customising serialisation of java collections using xstream

javacollectionsxml-serializationxstream

提问by Will Goring

I have an object that needs to be serialised as XML, which contains the following field:

我有一个需要序列化为 XML 的对象,其中包含以下字段:

List<String> tags = new List<String>();

XStream serialises it just fine (after some aliases) like this:

XStream 序列化它就好了(在一些别名之后),如下所示:

<tags>
  <string>tagOne</string>
  <string>tagTwo</string>
  <string>tagThree</string>
  <string>tagFour</string>
</tags>

That's OK as far as it goes, but I'd like to be able to rename the <string>elements to, say, <tag>. I can't see an obvious way to do that from the alias documentation on the XStream site. Am I missing something obvious?

就目前而言这没问题,但我希望能够将<string>元素重命名为<tag>. 我从 XStream 站点上的别名文档中看不到明显的方法来做到这一点。我错过了一些明显的东西吗?

采纳答案by Jim Ferrans

I'd suggest changing the List<String>to a List<Tag>, where Tag is a domain object that essentially just contains a String. Then you say:

我建议将 the 更改List<String>为 a List<Tag>,其中 Tag 是一个域对象,基本上只包含一个字符串。那你说:

xstream.alias("tag", org.goring.Tag.class);

and you get exactly what you want. This avoids having to roll your own Converter.

你会得到你想要的。这避免了必须推出自己的转换器。

回答by jitter

Out of interest I gave it a try to do it without writing my own converter. Basically I just register a special instructed version of CollectionConverterfor a certain field in a certain class.

出于兴趣,我尝试在不编写自己的转换器的情况下进行操作。基本上,我只是CollectionConverter为某个类中的某个字段注册了一个特殊的指导版本。

Relevant snippet:

相关片段:

ClassAliasingMapper mapper = new ClassAliasingMapper(xstream.getMapper());
mapper.addClassAlias("tag", String.class);
xstream.registerLocalConverter(
    Test.class,
    "tags",
    new CollectionConverter(mapper)
);

Full-blown example:

完整示例:

import com.thoughtworks.xstream.*;
import com.thoughtworks.xstream.converters.collections.*;
import com.thoughtworks.xstream.mapper.*;
import java.util.*;

public class Test {
    public List<String> tags = new ArrayList<String>();
    public List<String> notags = new ArrayList<String>();
    public Test(String tag, String tag2) {
        tags.add(tag); tags.add(tag2);
        notags.add(tag); notags.add(tag2);
    }
    public static void main(String[] args) {
        Test test = new Test("foo", "bar");
        XStream xstream = new XStream();

        ClassAliasingMapper mapper = new ClassAliasingMapper(xstream.getMapper());
        mapper.addClassAlias("tag", String.class);
        xstream.registerLocalConverter(
            Test.class,
            "tags",
            new CollectionConverter(mapper)
        );

        System.out.println(xstream.toXML(test));
    }
}


Not tested but this should work. No?

未经测试,但这应该有效。不?

xstream.alias("tag", java.lang.String.class);

回答by xjma86

@XStreamAlias("example")
public class A {
    private B myList;

    public A(){
        this.myList = new B();
    }

    public A clone(){
        A a = new A();
        a.myList = this.myList;
        return a;
    }

    public B getMyList() {
        return myList;
    }

    public void setMyList(B myList) {
        this.myList = myList;
    }   
}

public class B {
    @XStreamImplicit(itemFieldName = "myField")
    ArrayList<String> myFieldlist;

    public B(){
        this.myFieldlist = new ArrayList<String>();
    }

    public B clone(){
        B b = new B();
        b.myFieldlist = this.myFieldlist;
        return b;
    }

    public ArrayList<String> getMyFieldlist() {
            return myFieldlist;
    }

    public void setMyFieldlist(ArrayList<String> myFieldlist) {
        this.myFieldlist = myFieldlist;
    }
}


public class Test {
    public static void main(String[] args) {
        A a = new A();
        a.getMyList().getMyFieldlist().add("aa");
        a.getMyList().getMyFieldlist().add("bb");       

        XStream xs = new XStream(new DomDriver());  
        xs.processAnnotations(A.class);
        xs.processAnnotations(B.class);     

        System.out.println(xs.toXML(a));                
    }
}

xml result:

xml 结果:

<example>
  <myList>
    <myField>aa</myField>
    <myField>bb</myField>
  </myList>
</example>

回答by Esko

Add alias for the java.util.Stringclass. Okay, that may break something else elsewhere but in this exact case that should be enough.

java.util.String类添加别名。好的,这可能会破坏其他地方的其他内容,但在这种情况下应该足够了。

If you don't want to do the thing above, you can make your own converters (see this handy tutorial) which will help you achieve your goal. And don't be afraid of making your own converter either, they're really easy to implement.

如果您不想做上面的事情,您可以制作自己的转换器(请参阅此方便的教程),这将帮助您实现目标。也不要害怕制作自己的转换器,它们真的很容易实现。

回答by wandi.darko

@XStreamConverter(value=ListToStringXStreamConverter.class, strings={"tag"})
List<String> tags = new List<String>();

and in ListToStringXStreamConverter.java

并在 ListToStringXStreamConverter.java 中

public class ListToStringXStreamConverter implements Converter {

private String alias;

public ListToStringXStreamConverter(String alias) {
    super();
    this.alias = alias;
}

@SuppressWarnings("rawtypes")
@Override
public boolean canConvert(Class type) {
    return true;
}

@Override
public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {

    @SuppressWarnings("unchecked")
    List<String> list = (List<String>)source;

    for (String string : list) {
        writer.startNode(alias);
        writer.setValue(string);
        writer.endNode();
    }

}

@Override
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
    throw new UnsupportedOperationException("ListToStringXStreamConverter does not offer suport for unmarshal operation");
}

}

回答by Luciano Santos

for me works with the code below, using Strings:

对我来说,使用以下代码使用字符串:

xStream.alias("myTag", Person.class);
xStream.addImplicitCollection(Person.class, "myTag", "myTag", String.class);
public class Person{
    private ArrayList<String> myTag;
    // ...
}
<Person>
      <myTag>atrcxb2102</myTag>
      <myTag>sub3</myTag>
</Person>