1

我尝试在 scala 中使用 XStream,但看起来 XSteam 中的注释在 scala 中不起作用。在下面的代码中,只有@XStreamAlias 有效,我还附上了一个示例输出,有人可以帮忙吗?

@XStreamAlias("posts")
case class Posts(
  @XStreamAsAttribute tag: String,
  @XStreamAsAttribute total: String,
  @XStreamAsAttribute user: String,
  @XStreamImplicit(itemFieldName="post") posts: JList[Post])

@XStreamAlias("post")
case class Post(
  @XStreamAsAttribute description: String,
  @XStreamAsAttribute extended: String,
  @XStreamAsAttribute hash: String,
  @XStreamAsAttribute href: String,
  @XStreamAsAttribute shared: String,
  @XStreamAsAttribute tag: String,
  @XStreamAsAttribute time: String)


<posts>
  <tag>a</tag>
  <total>b</total>
  <user>c</user>
  <posts>
    <post>
      <description></description>
      <extended></extended>
      <hash></hash>
      <href></href>
      <shared></shared>
      <tag></tag>
      <time></time>
    </post>
  </posts>
</posts>
4

2 回答 2

2

这是一个老问题,但我最近遇到了类似的问题,我想将我的解决方案添加到它以供将来参考。

我想将 @XStreamAlias 用于案例类及其字段,并根据案例类注释从字符串中反序列化 XML:

import com.thoughtworks.xstream.XStream
import com.thoughtworks.xstream.annotations.XStreamAlias
import com.thoughtworks.xstream.io.xml.DomDriver

@XStreamAlias("TOP")
case class example(
                    @XStreamAlias("SUB")
                    val param : String) {

}

val xs = new XStream(new DomDriver())
xs.setClassLoader(getClass.getClassLoader)
xs.processAnnotations(example.getClass)

//OK
xs.fromXML(<TOP><param>x</param></TOP>.toString())

//Error - No such field sub   
xs.fromXML(<TOP><SUB>x</SUB></TOP>.toString())

问题是注释不适用于类字段。经过一番搜索,我发现 scala 为类字段生成了几个访问器(参见scala.annotation.meta),但默认情况下,注释仅应用于构造函数参数,而不应用于所有访问器。

要使注释也适用于该字段(规范/库对这些概念不明确,因此我假设它仅适用于该字段而不适用于访问器),您可以使用@(XStreamAlias @field)("SUB"). 这解决了我的问题:

@XStreamAlias("TOP")
case class example2 (
                    @(XStreamAlias @scala.annotation.meta.field)("SUB")
                    val param : String) {

}
val xs2 = new XStream(new DomDriver())
xs2.setClassLoader(getClass.getClassLoader)
xs2.processAnnotations(example.getClass)

//OK
val obj = xs2.fromXML(<TOP><SUB>x</SUB></TOP>.toString()).asInstanceOf[example2]

print(obj)
//> example2(x)
于 2016-05-12T09:00:34.030 回答
1

看起来 java 注释不能很好地与 Scala 配合使用。:-) 您必须依靠简单的旧方法语法来设置它。请参阅下面的代码片段,我查看了他们的 API 文档。

import com.thoughtworks.xstream.annotations._
import com.thoughtworks.xstream.XStream
import java.util.{ ArrayList => JList }

class Posts(
  val tag: String,
  val total: String,
  val user: String,
  val post: JList[Post])

class Post(
  val description: String,
  val extended: String,
  val hash: String,
  val href: String,
  val shared: String,
  val tag: String,
  val time: String)

object Main extends App {
  val xst = new XStream();
  val pp = new JList[Post]

  val rstv = new Post("a", "b", "c", "d", "e", "f", "g")
  pp.add(rstv)
  val postClazz = classOf[Post]
  val postsClazz = classOf[Posts]
  val pstv = new Posts("p", "q", "r", pp)

  xst.useAttributeFor(postsClazz, "tag")
  xst.useAttributeFor(postsClazz, "total")
  xst.useAttributeFor(postsClazz, "user")

  xst.useAttributeFor(postClazz, "description")
  xst.useAttributeFor(postClazz, "extended")
  xst.useAttributeFor(postClazz, "hash")
  xst.useAttributeFor(postClazz, "href")
  xst.useAttributeFor(postClazz, "shared")
  xst.useAttributeFor(postClazz, "tag")
  xst.useAttributeFor(postClazz, "time")
  val foo = xst.toXML(pstv)
  println(foo)
}

请注意,所有类都必须设置为由 XStream 查找的字段。使用此代码,我得到以下输出:

<Posts tag="p" total="q" user="r">
  <post>
    <Post description="a" extended="b" hash="c" href="d" shared="e" tag="f" time
="g"/>
  </post>
</Posts>

希望这可以帮助。

编辑:为了扩展我上面所说的内容,诸如@XStreamAliaset al 之类的注释已完全从编译的字节码中剥离。这可以通过运行javapscalap在那些编译的类上看到。这使我得出结论,Java 注释没有与 scala 注释同等对待(尽管理想情况下应该是 - 如果我犯了任何错误,请随意插话)。会很高兴学到一些东西。:-)

于 2012-12-29T10:59:42.300 回答