Scala中XStream的选项转换器

时间:2015-10-27 11:09:42

标签: scala xstream

我正在尝试使用Scala中的Xstream将类型为Option[T]的对象转换为XML。我有一个这样的案例类:

case class MyModel(promos: Option[Promos])

如果选项为Some(Promo),我希望它呈现

<MyModel>
  <Promos>
    <promoField1>value</promoField1>
    <promoField2>value</promoField2>
  </Promos>   
</MyModel>

如果选项为None,我希望它呈现

<MyModel>
  <Promos/>
</MyModel>

到目前为止,在我的解决方案中,我已经注册了一个转换器:

xstream.registerConverter(new OptionConverter(xstream.getMapper)) 

然后我有一个如下所示的自定义转换器:

private [xml] class OptionConverter(_mapper: Mapper) extends AbstractCollectionConverter(_mapper: Mapper) {

  override def marshal(source: scala.Any, writer: HierarchicalStreamWriter, context: MarshallingContext): Unit = {
    val opt = source.asInstanceOf[Option[_]]
    for (value <- opt) {
      writeItem(value, context, writer)
    }
  }

  override def unmarshal(reader: HierarchicalStreamReader, context: UnmarshallingContext): AnyRef = {
    throw new UnsupportedOperationException
  }

  override def canConvert(clazz: Class[_]): Boolean = {
    clazz.isAssignableFrom(classOf[Some[_]]) || clazz.isAssignableFrom(None.getClass)
  }
}

None工作正常,但Some(promo)输出如下:

<Promos>
  <com.mymodel.Promos>
    <promoField1>value</promoField1>
    <promoField2>value</promoField2>
  </com.mymodel.Promos>
</Promos>

问题是,正在为我的Option/Some字段输出Promos,然后输出“com.mymodel.Promos”作为Some内的嵌套值。有没有办法压扁Some(value)

1 个答案:

答案 0 :(得分:0)

我设法使Option转换器将对象编组为XML。 (我不需要阅读部分,所以我把它留下了未实现的内容)

import com.thoughtworks.xstream.converters.{MarshallingContext, UnmarshallingContext}
import com.thoughtworks.xstream.io.{HierarchicalStreamReader, HierarchicalStreamWriter}

private [xml] sealed class OptionConverter extends com.thoughtworks.xstream.converters.Converter {

  override def marshal(source: scala.Any, writer: HierarchicalStreamWriter, context: MarshallingContext): Unit = {
    val opt = source.asInstanceOf[Option[_]]
    for (value <- opt) {
      context.convertAnother(opt.get)
    }
  }

  override def unmarshal(reader: HierarchicalStreamReader, context: UnmarshallingContext): AnyRef = {
    throw new UnsupportedOperationException
  }

  override def canConvert(clazz: Class[_]): Boolean = {
    clazz.isAssignableFrom(classOf[Some[_]]) || clazz.isAssignableFrom(None.getClass)
  }
}