2009-11-24 18 views
11

Tengo un objeto que tiene que ser serializado como XML, que contiene el siguiente campo:personalización serialización de las colecciones de Java utilizando xstream

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

xstream serialises, estuvo bien (después de algunos alias) de esta manera:

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

eso está bien en lo que cabe, pero me gustaría ser capaz de cambiar el nombre de los elementos <string> a, digamos, <tag>. No veo una manera obvia de hacerlo desde la documentación del alias en el sitio de XStream. ¿Me estoy perdiendo algo obvio?

Respuesta

5

me gustaría sugerir el cambio de la List<String> a un List<Tag>, donde la etiqueta es un objeto de dominio que esencialmente sólo contiene una cadena. Luego diga:

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

y obtendrá exactamente lo que desea. Esto evita tener que hacer rodar su propio convertidor.

+0

Eso es exactamente lo que terminé haciendo hace media hora. Funcionó una delicia. :) –

+2

¿Podrían explicar cómo podría ser la clase Tag? Si sigo una variable de cadena (por ejemplo tagValue) en ella, me sale algo así como tagOne tagTwo. Gracias por adelantado. – Jonna

+1

Como dice Jonna anteriormente, no creo que esto le proporcione el resultado que desea, a menos que me esté perdiendo algo. Lo acabo de probar y encontré lo mismo que Jonna. La solución a continuación que usa el CollectionConverter y ClassAliasingMapper hizo lo que necesitaba en solo 3 líneas de código. – DaveyDaveDave

1

Agregue un alias para la clase java.util.String. Está bien, eso puede romper algo más en otro lugar pero en este caso exacto eso debería ser suficiente.

Si usted no quiere hacer lo anterior, usted puede hacer sus propios convertidores (see this handy tutorial), que le ayudará a alcanzar su meta. Y no tengas miedo de crear tu propio convertidor, son realmente fáciles de implementar.

+0

Gotcha. Esperaba evitar escribir mi propio convertidor, ya que la clase en cuestión tiene una tonelada de campos, pero si eso es lo que tengo que hacer ... Gracias.:) –

12

Fuera de interés lo intenté sin escribir mi propio convertidor. Básicamente, solo registro una versión especial instruida de CollectionConverter para cierto campo en cierta clase.

fragmento pertinente:

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

ejemplo en toda regla:

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

No se ha probado, pero esto debería funcionar. ¿No?

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

Funciona (lo probé), pero recoge y alias los miembros de otros Colección de cadenas en la clase también. Desafortunadamente en mi clase real (a diferencia del ejemplo) hay más de una colección. –

+0

Esta solución funciona perfectamente. Probado en XStream 1.3.1. Will> ¿cómo es posible? este tipo de alias se realiza solo en las "etiquetas" de campo de la clase Test y cada otra colección en la clase Test tiene alias la configuración predeterminada de los correlacionadores XStream (es decir, tienen la misma representación xml que en la publicación inicial ->. ..). –

+0

Will Gorings comment se refiere a la primera versión de mi respuesta. Que es el oneliner debajo de la línea horizontal – 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));     
    } 
} 

resultado xml:

<example> 
    <myList> 
    <myField>aa</myField> 
    <myField>bb</myField> 
    </myList> 
</example> 
0
@XStreamConverter(value=ListToStringXStreamConverter.class, strings={"tag"}) 
List<String> tags = new List<String>(); 

y en 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

para mí funciona con el código de abajo, el uso de cadenas:

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> 
Cuestiones relacionadas