Search

17.4. JAXB and JSON provider

download PDF
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:
@XmlRootElement(name = "book")
public class Book {

   private String author;
   private String ISBN;
   private String title;

   public Book() {
   }

   public Book(String author, String ISBN, String title) {
      this.author = author;
      this.ISBN = ISBN;
      this.title = title;
   }

   @XmlElement
   public String getAuthor() {
      return author;
   }

   public void setAuthor(String author) {
      this.author = author;
   }

   @XmlElement
   public String getISBN() {
      return ISBN;
   }

   public void setISBN(String ISBN) {
      this.ISBN = ISBN;
   }

   @XmlAttribute
   public String getTitle() {
      return title;
   }

   public void setTitle(String title) {
      this.title = title;
   }
}


The JAXB Book class would be marshalled to JSON using the BadgerFish Convention:
 {"book":
    {
       "@title":"EJB 3.0",
       "author":{"$":"Bill Burke"},
       "ISBN":{"$":"596529260"}
    }
 }
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.$;
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 {...}
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(...) {...}
If your input is a Book, place it on the parameter:
 @POST
 public void newBook(@BadgerFish Book book) {...}
The default Jettison Mapped Convention returns the following JSON:
 { "book" :
      {
         "@title":"EJB 3.0",
         "author":"Bill Burke",
         "ISBN":596529260
       }
 }
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;
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;
You must define a JSON-to-XML namespace mapping, or you will receive an exception:
java.lang.IllegalStateException: Invalid JSON namespace:
  http://jboss.org/books
at org.codehaus.jettison.mapped.MappedNamespaceConvention
  .getJSONNamespace(MappedNamespaceConvention.java:151)
at org.codehaus.jettison.mapped.MappedNamespaceConvention
  .createKey(MappedNamespaceConvention.java:158)
at org.codehaus.jettison.mapped.MappedXMLStreamWriter
  .writeStartElement(MappedXMLStreamWriter.java:241)
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.
 import org.jboss.resteasy.annotations.providers.jaxb.json.Mapped;
 import org.jboss.resteasy.annotations.providers.jaxb.json.XmlNsMap;

 ...

@GET
@Produces("application/json")
@Mapped(namespaceMap = {
        @XmlNsMap(namespace = "http://jboss.org/books", jsonName = "books")
})
public Book get() {...}

You can also force @XmlAttributes to be marshalled as XMLElements.
            @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(...) {...}
If your input is a Book, place it on the parameter:
 @POST
 public void newBook(@Mapped(attributeAsElements={"title"}) Book book) {...}
Red Hat logoGithubRedditYoutubeTwitter

Learn

Try, buy, & sell

Communities

About Red Hat Documentation

We help Red Hat users innovate and achieve their goals with our products and services with content they can trust.

Making open source more inclusive

Red Hat is committed to replacing problematic language in our code, documentation, and web properties. For more details, see the Red Hat Blog.

About Red Hat

We deliver hardened solutions that make it easier for enterprises to work across platforms and environments, from the core datacenter to the network edge.

© 2024 Red Hat, Inc.