How can I get XStream to output Scala lists nicely? Can I write a custom converter?

安稳与你 提交于 2019-12-19 03:10:41

问题


This code:

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

produces this XML:

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

Instead I'd like this:

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

Which would be similar to how the generic java collections get serialized. Whats the best way to do this?

I've got most of the way there by implementing my own converter, but I'm stuck on the unmarshal method, its not clear how to instantiate an empty list...

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

回答1:


Not seconds after posting the question, the answer came to me, here is a working implementation of 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
  }



回答2:


There is only one instance of an empty list, which is the object Nil.



来源:https://stackoverflow.com/questions/1753511/how-can-i-get-xstream-to-output-scala-lists-nicely-can-i-write-a-custom-convert

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!