2009-11-18 5 views
6

Ce code:Comment puis-je faire en sorte que XStream affiche correctement les listes Scala? Puis-je écrire un convertisseur personnalisé?

println(new XStream.toXML(List(1,2,3))) 

produit ce XML:

<scala.coloncolon serialization="custom"> 
    <unserializable-parents/> 
    <scala.coloncolon> 
    <int>1</int> 
    <int>2</int> 
    <int>3</int> 
    <scala.ListSerializeEnd/> 
    </scala.coloncolon> 
</scala.coloncolon> 

Au lieu de cela, je voudrais que cela:

<list> 
    <int>1</int> 
    <int>2</int> 
    <int>3</int> 
</list> 

qui serait similaire à la façon dont les collections Java génériques se sérialisé. Quel est le meilleur moyen de le faire?

J'ai la plupart du chemin en mettant en place mon propre convertisseur, mais je suis bloqué sur la méthode unmarshal, son ne sait pas comment instancier une liste vide ...

class ListConverter(_mapper : Mapper) extends AbstractCollectionConverter(_mapper) { 
    /** Helper method to use x.getClass 
    * 
    * See: http://scalide.blogspot.com/2009/06/getanyclass-tip.html 
    */ 
    def getAnyClass(x: Any) = x.asInstanceOf[AnyRef].getClass 

    def canConvert(clazz: Class[_]) = {  
    classOf[::[_]] == clazz 
    } 

    def marshal(value: Any, writer: HierarchicalStreamWriter, context: MarshallingContext) = { 
    val list = value.asInstanceOf[List[_]] 
    for (item <- list) {  
     writeItem(item, context, writer) 
    } 
    } 

    def unmarshal(reader: HierarchicalStreamReader, context: UnmarshallingContext) = { 
    println(context.getRequiredType()) 
    var list : List[_] = createCollection(context.getRequiredType()).asInstanceOf[List[_]] 
    while (reader.hasMoreChildren()) { 
     reader.moveDown(); 
     val item = readItem(reader, context, list); 
     list = item :: list 
     reader.moveUp(); 
    } 
    list 
    } 
} 

object ListConverter { 
    def configureXStream(stream: XStream) = { 
    stream.alias("list", classOf[::[_]]) 
    stream.registerConverter(new ListConverter(stream.getMapper))   
    } 
} 

Répondre

2

Non secondes après avoir affiché la question, la réponse est venue à moi, voici une implémentation fonctionnelle de unmarshal:

def unmarshal(reader: HierarchicalStreamReader, context: UnmarshallingContext) = { 
    var list : List[_] = Nil 
    while (reader.hasMoreChildren()) { 
     reader.moveDown(); 
     val item = readItem(reader, context, list); 
     list = list ::: List(item) // be sure to build the list in the same order 
     reader.moveUp(); 
    } 
    list 
    } 
1

Il n'y a qu'une seule instance d'une liste vide, qui est l'objet Nil.

+0

Pouvez-vous élaborer? Je ne vois pas la pertinence de votre réponse à la question –

+0

Vous avez demandé comment vous pouviez instancier une liste vide. Je dis juste qu'il n'y a qu'une liste vide, qui est 'Nil'. Vous devez donc vous référer à cela - comme vous l'avez fait dans le code que vous avez indiqué dans votre réponse. –

+0

Dire parfaitement logique maintenant que vous l'expliquez, merci! –

Questions connexes