6 Stimmen

Wie kann ich XStream zu bekommen, um Scala-Listen schön ausgeben? Kann ich einen eigenen Konverter schreiben?

Dieser Code:

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

erzeugt dieses XML:

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

Stattdessen möchte ich dies:

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

Das wäre ähnlich, wie die generischen Java-Sammlungen serialisiert werden. Was ist der beste Weg, dies zu tun?

Ich habe die meisten der Weg dorthin durch die Implementierung meiner eigenen Konverter, aber ich bin auf die unmarshal-Methode stecken, seine nicht klar, wie eine leere Liste zu instanziieren...

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

2voto

Alex Black Punkte 13274

Keine Sekunden nachdem ich die Frage gestellt hatte, fiel mir die Antwort ein: Hier ist eine funktionierende Implementierung von 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
  }

1voto

Daniel C. Sobral Punkte 290004

Es gibt nur ein Beispiel für eine leere Liste, nämlich das Objekt Nil .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X