ScalaXB生成Case Class添加JAXB注解及XSD转Java替代SBT库咨询
问题背景
我目前在用ScalaXB插件把XSD文件转换成Scala case class,转换本身没问题,但现在想给生成的类加上javax.xml.bind.annotation相关注解,用来配合JAXB做XML的序列化和反序列化。不过现在遇到了报错:JAXB提示生成的类没有无参构造函数。如果ScalaXB没法实现这个需求的话,有没有其他还在活跃维护的SBT库可以把XSD转换成Java文件?我之前找到过sbt-xjc,但感觉它已经不怎么更新了。
附一下目前ScalaXB生成的代码示例:
// Generated by scalaxb. package generated case class EmployeeType(FirstName: String, LastName: String, Age: Int, Email: String)
还有我用的JAXB反序列化代码:
import javax.xml.bind._ import java.io.StringReader def unmarshalXML[T](xmlString: String)(implicit tag: reflect.ClassTag[T]): Option[T] = { try { val context = JAXBContext.newInstance(tag.runtimeClass) val unmarshaller = context.createUnmarshaller() val instance = unmarshaller.unmarshal(new StringReader(xmlString)).asInstanceOf[T] Some(instance) } catch { case ex: Exception => ex.printStackTrace() None } }
报错栈信息:
Exception in thread "main" com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
generated.EmployeeType does not have a no-arg default constructor.
this problem is related to the following location:
at generated.EmployeeType
解决方案
1. 给ScalaXB开启JAXB注解生成配置
其实ScalaXB本身就支持生成JAXB所需的注解和无参构造函数,你只需要在build.sbt里添加对应的配置即可:
scalaxbGenerateJaxbAnnotations := true
开启这个配置后,ScalaXB生成的case class会自动带上@XmlRootElement、@XmlElement等JAXB注解,同时还会生成无参构造函数(这正是JAXB要求的)。生成后的代码会类似这样:
package generated import javax.xml.bind.annotation._ @XmlRootElement(name = "EmployeeType") case class EmployeeType(var FirstName: String, var LastName: String, var Age: Int, var Email: String) { def this() = this("", "", 0, "") }
这样你的JAXB反序列化方法就能正常工作了,既不用修改现有代码结构,又满足了JAXB的要求。
2. 替代sbt-xjc的活跃XSD转Java SBT库
如果你确实需要把XSD转换成Java类,推荐使用sbt-jaxb,这是目前维护状态良好的替代方案,配置步骤如下:
首先在project/plugins.sbt中添加插件依赖:
addSbtPlugin("com.github.sbt" % "sbt-jaxb" % "2.0.0")
然后在build.sbt里配置XSD文件的路径和生成规则:
jaxbSettings // 把JAXB生成的Java类加入编译源 sourceGenerators in Compile += (jaxbGenerate in Compile).taskValue // 指定XSD文件所在目录 jaxbXsdDir in Compile := file("src/main/xsd")
配置完成后,执行sbt compile,插件就会自动把src/main/xsd下的XSD文件转换成带JAXB注解的Java类,生成的文件会放在target/scala-[版本号]/src_managed/main目录下,这些类会自动参与项目编译,完全满足你的序列化需求。
备注:内容来源于stack exchange,提问作者Prabhat Kashyap

