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

发布于 2024-08-12 10:24:16 字数 497 浏览 8 评论 0原文

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

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

XStream 将其序列化得很好(在一些别名之后),如下所示:

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

就目前而言还可以,但我希望能够重命名 元素到 。从 XStream 站点上的别名文档中我看不到明显的方法来做到这一点。我错过了一些明显的事情吗?

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

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

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

<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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

深巷少女 2024-08-19 10:24:16

出于兴趣,我尝试在不编写自己的转换器的情况下做到这一点。基本上我只是为某个类中的某个字段注册一个特殊指令版本的CollectionConverter

相关片段:

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

完整的示例:

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));
    }
}

未经测试,但这应该可行。不?

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

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 CollectionConverter for a certain field in a certain class.

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);
巴黎夜雨 2024-08-19 10:24:16

我建议将 List 更改为 List,其中 Tag 是一个域对象,本质上只包含一个 String。然后你说:

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

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

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:

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

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

小伙你站住 2024-08-19 10:24:16
@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 结果:

<example>
  <myList>
    <myField>aa</myField>
    <myField>bb</myField>
  </myList>
</example>
@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:

<example>
  <myList>
    <myField>aa</myField>
    <myField>bb</myField>
  </myList>
</example>
深爱成瘾 2024-08-19 10:24:16

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

如果您不想执行上述操作,您可以制作自己的转换器(看到这个方便教程)这将帮助您实现您的目标。也不要害怕制作自己的转换器,它们非常容易实现。

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

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.

£噩梦荏苒 2024-08-19 10:24:16
@XStreamConverter(value=ListToStringXStreamConverter.class, strings={"tag"})
List<String> tags = new List<String>();

并在 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");
}

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

and in 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");
}

}
奈何桥上唱咆哮 2024-08-19 10:24:16

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

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>

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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文