2009-11-24 16 views
11

Ho un oggetto che deve essere serializzato come XML, che contiene il seguente campo:personalizzazione serializzazione delle collezioni Java utilizzando xstream

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

XStream serialises proprio bene (dopo alcuni alias) in questo modo:

Questo va bene così com'è, ma mi piacerebbe poter rinominare gli elementi <string>, ad esempio, <tag>. Non riesco a vedere un modo ovvio per farlo dalla documentazione degli alias sul sito XStream. Mi manca qualcosa di ovvio?

risposta

5

Io suggerirei di cambiare il List<String> ad un List<Tag>, dove Tag è un oggetto di dominio che essenzialmente solo contiene una stringa. Quindi dici:

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

e ottieni esattamente ciò che desideri. Questo evita di dover girare il tuo convertitore.

+0

Questo è esattamente quello che ho fatto circa mezz'ora fa. Ha funzionato a meraviglia. :) –

+2

Potresti per favore approfondire come potrebbe essere la classe Tag? Se continuo a una variabile stringa (diciamo tagValue) in esso, ottengo qualcosa come tagOne tagTwo. Grazie in anticipo. – Jonna

+1

Come dice Jonna sopra, non penso che questo ti darà l'output che vuoi, a meno che mi manchi qualcosa. L'ho appena provato e ho trovato lo stesso di Jonna. La soluzione qui sotto utilizzando CollectionConverter e ClassAliasingMapper ha fatto ciò che mi serviva solo in 3 righe di codice. – DaveyDaveDave

1

Aggiungere alias per la classe java.util.String. Ok, questo potrebbe rompere qualcos'altro altrove, ma in questo caso esatto dovrebbe essere sufficiente.

Se non si desidera eseguire l'operazione precedente, è possibile creare convertitori personalizzati (see this handy tutorial) che consentiranno di raggiungere il proprio obiettivo. E non aver paura di creare il tuo convertitore, sono davvero facili da implementare.

+0

Gotcha. Speravo di evitare di scrivere il mio convertitore, poiché la classe in questione ha una tonnellata di campi, ma se è quello che devo fare ... Grazie.:) –

12

Per interesse, ho provato a farlo senza scrivere il mio convertitore. Fondamentalmente mi limito a registrare una versione speciale di CollectionConverter per un determinato campo in una determinata classe.

Rilevante frammento:

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

conclamato esempio:

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

Non testato, ma questo dovrebbe funzionare. No?

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

Funziona (l'ho appena provato), ma raccoglie e alias i membri di qualsiasi altra raccolta di stringhe nella classe pure. Sfortunatamente nella mia vera classe (a differenza dell'esempio) c'è più di una tale Collezione. –

+0

Questa soluzione funziona perfettamente. Testato su XStream 1.3.1. Sarà> come è possibile? . Questo tipo di aliasing è fatto solo sul campo "tag" di classe di test e di ogni altra raccolta in classe Test è aliasing dalle impostazioni di default di mapper XStream (vale a dire che hanno stessa rappresentazione XML come si scrive nel vostro post iniziale ->. ..). –

+0

Il commento di Gorings riguarda la prima versione della mia risposta. Quale è l'oneliner sotto la linea orizzontale – 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));     
    } 
} 

risultato xml:

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

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

} 
0

per me funziona con il codice qui sotto, utilizzando le stringhe:

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> 
Problemi correlati