如何将Scala列表与JAXB一起使用?

时间:2017-08-19 20:02:54

标签: scala jaxb

短版

如何在

中注释list属性
case class Foo(list: List[String])

能够使用JAXB序列化吗?

长版

这是我到目前为止所尝试的内容。我使用@XmlElements和@XmlJavaTypeAdapter注释对该属性进行了注释,请参阅类ScalaFoo。但是ScalaFoo序列化失败,但下面有例外,而JavaFoo正常工作。

import java.util
import javax.xml.bind.annotation._
import javax.xml.bind.annotation.adapters._

import ListTest.{xmlElement, xmlElements, xmlTypeAdapter}

import scala.annotation.meta.field
import scala.collection.JavaConverters._

object ListTest extends App {
    type xmlElement = XmlElement@field
    type xmlElements = XmlElements@field
    type xmlTypeAdapter = XmlJavaTypeAdapter@field

    import com.sun.jersey.api.json._

    val config  = JSONConfiguration.natural().rootUnwrapping(true).build()
    val context = new JSONJAXBContext(config, classOf[JavaFoo], classOf[ScalaFoo])

    val javaFoo  = JavaFoo(util.Arrays.asList("a"))
    val scalaFoo = ScalaFoo(List("a"))

    context.createJSONMarshaller().marshallToJSON(javaFoo, System.out)
    context.createJSONMarshaller().marshallToJSON(scalaFoo, System.out)
}

class ListAdapter[A] extends XmlAdapter[java.util.List[A], List[A]] {
    def marshal(v: List[A]): util.List[A] = new util.ArrayList(v.asJava)
    def unmarshal(v: java.util.List[A]): List[A] = v.asScala.toList
}

@XmlRootElement(name = "foo")
@XmlAccessorType(XmlAccessType.FIELD)
case class JavaFoo(@xmlElements(value = Array(new xmlElement(`type` = classOf[String])))
                   list: java.util.List[String]) {
    private def this() = this(null)
}

@XmlRootElement(name = "foo")
@XmlAccessorType(XmlAccessType.FIELD)
case class ScalaFoo(@xmlTypeAdapter(classOf[ListAdapter[String]])
                    @xmlElements(value = Array(new xmlElement(`type` = classOf[String])))
                    list: List[String]) {
    private def this() = this(null)
}

例外:

Exception in thread "main" javax.xml.bind.MarshalException
 - with linked exception:
[com.sun.istack.SAXException2: class java.util.ArrayList nor any of its super class is known to this context.
javax.xml.bind.JAXBException: class java.util.ArrayList nor any of its super class is known to this context.]
    at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:323)
    at com.sun.xml.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:177)
    at com.sun.jersey.json.impl.JSONMarshallerImpl.marshal(JSONMarshallerImpl.java:94)
    at com.sun.jersey.json.impl.BaseJSONMarshaller.marshallToJSON(BaseJSONMarshaller.java:106)
    at com.sun.jersey.json.impl.BaseJSONMarshaller.marshallToJSON(BaseJSONMarshaller.java:94)
    at ListTest$.delayedEndpoint$ListTest$1(ListTest.scala:26)
    at ListTest$delayedInit$body.apply(ListTest.scala:12)
    at scala.Function0.apply$mcV$sp(Function0.scala:34)
    at scala.Function0.apply$mcV$sp$(Function0.scala:34)
    at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
    at scala.App.$anonfun$main$1$adapted(App.scala:76)
    at scala.collection.immutable.List.foreach(List.scala:389)
    at scala.App.main(App.scala:76)
    at scala.App.main$(App.scala:74)
    at ListTest$.main(ListTest.scala:12)
    at ListTest.main(ListTest.scala)
Caused by: com.sun.istack.SAXException2: class java.util.ArrayList nor any of its super class is known to this context.
javax.xml.bind.JAXBException: class java.util.ArrayList nor any of its super class is known to this context.
    at com.sun.xml.bind.v2.runtime.XMLSerializer.reportError(XMLSerializer.java:250)
    at com.sun.xml.bind.v2.runtime.XMLSerializer.reportError(XMLSerializer.java:265)
    at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:657)
    at com.sun.xml.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:153)
    at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:344)
    at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsSoleContent(XMLSerializer.java:597)
    at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeRoot(ClassBeanInfoImpl.java:328)
    at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:498)
    at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:320)
    ... 15 more
Caused by: javax.xml.bind.JAXBException: class java.util.ArrayList nor any of its super class is known to this context.
    at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getBeanInfo(JAXBContextImpl.java:611)
    at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:652)
    ... 21 more

0 个答案:

没有答案