Skip to content

Instantly share code, notes, and snippets.

@vic0nt
Forked from krasserm/jaxb-01.scala
Last active November 16, 2020 04:58
Show Gist options
  • Save vic0nt/7689849 to your computer and use it in GitHub Desktop.
Save vic0nt/7689849 to your computer and use it in GitHub Desktop.
import javax.xml.bind.annotation._
@XmlRootElement(name = "person")
@XmlAccessorType(XmlAccessType.FIELD)
case class Person(fullname: String, username: Option[String], age: Int)
import scala.annotation.target.field
import javax.xml.bind.annotation._
import javax.xml.bind.annotation.adapters._
import java.util.{List => JList}
import java.util.{ArrayList => JArrayList}
import java.util.{Arrays => JArrays}
import common.Types.{xmlElements, xmlTypeAdapter, xmlElement}
type xmlElement = XmlElement @field
type xmlTypeAdapter = XmlJavaTypeAdapter @field
type xmlElements = XmlElements @field
class StringOptionAdapter extends OptionAdapter[String](null, "")
class OptionAdapter[A](nones: A*) extends XmlAdapter[A, Option[A]] {
def marshal(v: Option[A]): A = v.getOrElse(nones(0))
def unmarshal(v: A) = if (nones contains v) None else Some(v)
}
@XmlRootElement(name = "person")
@XmlAccessorType(XmlAccessType.FIELD)
case class Person(
@xmlElement(required = true) fullname: String,
@xmlTypeAdapter(classOf[StringOptionAdapter]) username: Option[String],
age: Int,
@XmlElementWrapper favNumbers: FavNumbers){
// only needed and accessed by JAXB
private def this() = this("", None, 0, FavNumbers(new JArrayList[Int]))
}
@XmlAccessorType(XmlAccessType.FIELD)
case class FavNumbers(
@xmlElements(
value = Array(new xmlElement(name="favNumber", `type` = classOf[Int]))
)
favNumbers: JList[Int]
){
private def this() = this(new JArrayList[Int])
}
import javax.xml.bind._
import javax.xml.transform.stream.StreamResult
val context = JAXBContext.newInstance(classOf[Person])
context.generateSchema(new SchemaOutputResolver {
def createOutput(namespaceUri: String, suggestedFileName: String) = {
val res = new StreamResult(System.out)
res.setSystemId(suggestedFileName)
res
}
})
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="person" type="person"/>
<xs:complexType name="person">
<xs:sequence>
<xs:element name="fullname" type="xs:string"/>
<xs:element name="username" type="xs:string" minOccurs="0"/>
<xs:element name="age" type="xs:int"/>
<xs:element name="favNumbers">
<xs:complexType>
<xs:sequence>
<xs:element name="favNumber" type="xs:integer" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:schema>
context.createMarshaller.marshal(Person("Martin Krasser", Some("krasserm"), 30 /* haha */), System.out)
<person>
<fullname>Martin Krasser</fullname>
<username>krasserm</username>
<age>30</age>
</person>
val personXml1 = "<person><fullname>Martin Krasser</fullname><username>mrt1nz</username><age>30</age><favNumbers><favNumber>73</favNumber><favNumber>47</favNumber></favNumbers></person>"
val personXml2 = "<person><fullname>Martin Krasser</fullname><age>30</age><favNumbers /></person>"
assert(context.createUnmarshaller().unmarshal(new StringReader(personXml1)) ==
Person("Martin Krasser", Some("mrt1nz"), 30, FavNumbers(new JArrayList[Int](JArrays.asList(73,47)))))
assert(context.createUnmarshaller().unmarshal(new StringReader(personXml2)) ==
Person("Martin Krasser", None, 30, FavNumbers(new JArrayList[Int])))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment