XStream注释在scala中不起作用

时间:2012-12-29 07:59:55

标签: scala annotations xstream

我尝试在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>

2 个答案:

答案 0 :(得分: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>

希望这会有所帮助。

编辑:为了扩展我上面所说的内容,@XStreamAlias等注释完全从编译后的字节码中删除。通过在这些编译的类上运行javapscalap可以看出这一点。这使我得出结论,java注释与scala注释并不相同(尽管理想情况下它应该是 - 如果我犯了任何错误,可以随意加入)。很高兴学到一些东西。 : - )

答案 1 :(得分:1)

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

我想在案例类及其字段中使用@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)