Skip to content

Instantly share code, notes, and snippets.

@krasserm
Created February 23, 2012 08:23
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save krasserm/1891525 to your computer and use it in GitHub Desktop.
Save krasserm/1891525 to your computer and use it in GitHub Desktop.
JAXB-based XML and JSON APIs
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._
type xmlElement = XmlElement @field
type xmlTypeAdapter = XmlJavaTypeAdapter @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) {
// only needed and accessed by JAXB
private def this() = this("", None, 0)
}
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: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><age>30</age></person>"
val personXml2 = "<person><fullname>Martin Krasser</fullname><username>mrt1nz</username><age>30</age></person>"
assert(context.createUnmarshaller().unmarshal(new StringReader(personXml1)) ==
Person("Martin Krasser", None, 30))
assert(context.createUnmarshaller().unmarshal(new StringReader(personXml2)) ==
Person("Martin Krasser", Some("mrt1nz"), 30))
import com.sun.jersey.api.json._
val config = JSONConfiguration.natural().rootUnwrapping(false).build()
val context = new JSONJAXBContext(config, classOf[Person])
context.createJSONMarshaller().marshallToJSON(person, System.out)
{"person":{"fullname":"Martin Krasser","username":"krasserm","age":30}}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment