17.4. JAXB and JSON provider
RESTEasy lets you marshal JAXB annotated POJOs to and from JSON with the Jettison JSON library. You can find more information about Jettison at http://jettison.codehaus.org/.
Jettison has two mapping formats: the default Jettison Mapped Convention format, and BadgerFish.
For example, consider this JAXB class:
The JAXB
Book
class would be marshalled to JSON using the BadgerFish Convention:
Element values are associated with a map. To find the value of the element, you must access the
$
variable. You could access the book like this, in JavaScript:
var data = eval("(" + xhr.responseText + ")"); document.getElementById("zone").innerHTML = data.book.@title; document.getElementById("zone").innerHTML += data.book.author.$;
var data = eval("(" + xhr.responseText + ")");
document.getElementById("zone").innerHTML = data.book.@title;
document.getElementById("zone").innerHTML += data.book.author.$;
To use the BadgerFish Convention you must use the
@org.jboss.resteasy.annotations.providers.jaxb.json.BadgerFish
annotation either on the JAXB class you are marshalling or unmarshalling, or on the JAX-RS resource method or parameter:
@BadgerFish @XmlRootElement(name = "book") public class Book {...}
@BadgerFish
@XmlRootElement(name = "book")
public class Book {...}
To return a
book
on the JAX-RS method without polluting your JAXB classes with RESTEasy annotations, you can add the annotation to the JAX-RS method instead:
@BadgerFish @GET public Book getBook(...) {...}
@BadgerFish
@GET
public Book getBook(...) {...}
If your input is a
Book
, place it on the parameter:
@POST public void newBook(@BadgerFish Book book) {...}
@POST
public void newBook(@BadgerFish Book book) {...}
The default Jettison Mapped Convention returns the following JSON:
Note that
title
is prefixed with the @
character. Unlike the BadgerFish convention, this does not represent the value of element text, which makes it simpler (and a sensible default). To access this in JavaScript:
var data = eval("(" + xhr.responseText + ")"); document.getElementById("zone").innerHTML = data.book.@title; document.getElementById("zone").innerHTML += data.book.author;
var data = eval("(" + xhr.responseText + ")");
document.getElementById("zone").innerHTML = data.book.@title;
document.getElementById("zone").innerHTML += data.book.author;
The Mapped Convention lets you adjust the JAXB mapping with the
@org.jboss.resteasy.annotations.providers.jaxb.json.Mapped
annotation. With this, you can provide an XML namespace to JSON namespace mapping. For example, if you define your JAXB namespace within your package-info.java
class like so:
@javax.xml.bind.annotation.XmlSchema(namespace="http://jboss.org/books") package org.jboss.resteasy.test.books;
@javax.xml.bind.annotation.XmlSchema(namespace="http://jboss.org/books")
package org.jboss.resteasy.test.books;
You must define a JSON-to-XML namespace mapping, or you will receive an exception:
The
@Mapped
annotation fixes this problem. Place the @Mapped
annotation on your JAXB classes, your JAX-RS resource method, or on the parameter that you are unmarshalling.
You can also force
@XmlAttribute
s to be marshalled as XMLElements
.
@Mapped(attributeAsElements={"title"}) @XmlRootElement(name = "book") public class Book {...}
@Mapped(attributeAsElements={"title"})
@XmlRootElement(name = "book")
public class Book {...}
To return a
book
on the JAX-RS method without polluting your JAXB classes with RESTEasy annotations, add the annotation to the JAX-RS method:
@Mapped(attributeAsElements={"title"}) @GET public Book getBook(...) {...}
@Mapped(attributeAsElements={"title"})
@GET
public Book getBook(...) {...}
If your input is a
Book
, place it on the parameter:
@POST public void newBook(@Mapped(attributeAsElements={"title"}) Book book) {...}
@POST
public void newBook(@Mapped(attributeAsElements={"title"}) Book book) {...}