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}} |