2009-11-24 1 views
11

У меня есть объект, который должен быть сериализовать XML, который содержит следующие поля:пользовательская настройка Сериализация коллекций ява с использованием XStream

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

XStream serialises это просто отлично (после нескольких псевдонимов), как это:

Это нормально, насколько это возможно, но я хотел был бы иметь возможность переименовать элементы <string>, скажем, <tag>. Я не вижу очевидного способа сделать это из документации псевдонима на сайте XStream. Мне что-то не хватает?

ответ

5

Я хотел бы предложить, изменяя List<String> к List<Tag>, где Tag является объект домена, который по существу только содержит строку. Затем вы говорите:

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

и вы получаете именно то, что хотите. Это позволяет избежать необходимости конвертировать собственный конвертер.

+0

Это именно то, что я закончил делать примерно полчаса назад. Работал. :) –

+2

Не могли бы вы рассказать о том, как может быть класс Tag? Если я держу строку переменной (скажем tagValue) в нем, я получаю что-то вроде tagOne tagTwo. Заранее спасибо. – Jonna

+1

Как говорит Йонна выше, я не думаю, что это даст вам результат, который вы хотите, если я не упустил что-то. Я только что попробовал и нашел то же самое, что и Джонна. Решение ниже с использованием CollectionConverter и ClassAliasingMapper делало то, что мне нужно только в 3 строках кода. – DaveyDaveDave

1

Добавить псевдоним для класса java.util.String. Хорошо, это может сломать что-то еще в другом месте, но в этом конкретном случае этого должно быть достаточно.

Если вы не хотите делать что-то выше, вы можете сделать свои собственные конвертеры (see this handy tutorial), которые помогут вам достичь своей цели. И не бойтесь создавать свой собственный конвертер, их действительно легко реализовать.

+0

Гоча. Я надеялся избежать написания собственного конвертера, так как у рассматриваемого класса есть тонна полей, но если это то, что я должен сделать ... Спасибо.:) –

12

Из интереса я попробовал сделать это, не написав свой собственный конвертер. В основном я просто зарегистрирую специальную заданную версию 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); 
+0

Он действительно работает (я просто попробовал), но он поднимает и псевдонимы членов любого других Коллекция строк в классе, а также. К сожалению, в моем реальном классе (в отличие от примера) есть более одной такой коллекции. –

+0

Это решение работает отлично. Протестировано на XStream 1.3.1. Will> как это возможно? этот вид наложения выполняется только в полевых тегах Test-класса, и каждая другая коллекция в классе Test сглаживается по умолчанию настройками XStream-mappers (т. е. они имеют одно и то же представление xml, которое вы пишете в своем начальном сообщении ->. ..). –

+0

Комментарий Горинга относится к первой версии моего ответа. Что является oneliner ниже горизонтальной линии – jitter

2
@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> 
0
@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"); 
} 

} 
0

работает для меня на код ниже, с помощью строк:

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> 
Смежные вопросы