Scala 中 XStream 的选项转换器

Option converter for XStream in Scala

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

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,然后为 Some 中的嵌套值输出 "com.mymodel.Promos"。 Some(value)?

有没有办法展平

我设法使 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)
  }
}