1

XStream を scala で使用しようとしていますが、XSteam のアノテーションが scala で機能していないようです。次のコードでは、@XStreamAlias のみが機能します。サンプル出力も 1 つ添付します。

@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 がクラス フィールドへのいくつかのアクセサーを生成することがわかりました (cf. 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 などの注釈は、コンパイルされたバイトコードから完全に削除されました。これは、これらのコンパイルされたクラスを実行javapまたは実行することで確認できます。scalapこれにより、Java アノテーションは scala アノテーションと同等に扱われていないという結論に達しました (しかし、理想的にはそうあるべきです - 間違いを犯した場合は遠慮なく声をかけてください)。何かを学べば幸いです。:-)

于 2012-12-29T10:59:42.300 に答える