我尝试在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>
答案 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
等注释完全从编译后的字节码中删除。通过在这些编译的类上运行javap
或scalap
可以看出这一点。这使我得出结论,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)