настройка сериализации коллекций java с помощью xstream
у меня есть объект, который должен быть сериализован как XML, который содержит следующее поле:
List<String> tags = new List<String>();
кинокомпании xStream serialises это просто отлично (после некоторых псевдонимов) такой:
<tags>
<string>tagOne</string>
<string>tagTwo</string>
<string>tagThree</string>
<string>tagFour</string>
</tags>
это нормально, но я хотел бы иметь возможность переименовать <string>
элементы, скажем, <tag>
. Я не вижу очевидного способа сделать это из документации псевдонима на сайте XStream. Я упускаю что-то очевидное?
6 ответов
Я бы предложил изменить List<String>
до List<Tag>
, где тег-это объект домена, который по существу содержит только строку. Тогда вы говорите:
xstream.alias("tag", org.goring.Tag.class);
и вы получаете именно то, что хотите. Это позволяет избежать необходимости сворачивать собственный конвертер.
из интереса я дал ему попробовать сделать это без написания мой собственный конвертер. В основном я просто регистрирую специальную версию 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);
@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>
добавить псевдоним java.util.String
класса. Хорошо, это может сломать что-то еще в другом месте, но в этом случае этого должно быть достаточно.
Если вы не хотите делать это выше, вы можете сделать свои собственные конвертеры (посмотреть этот удобный учебник), который поможет вам достичь своей цели. И не бойтесь делать свой собственный конвертер, они действительно просты в реализации.
@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");
}
}
для меня работает с кодом, приведенным ниже, используя строки:
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>