Difference between revisions of "EclipseLink/Examples/MOXy/JSON Twitter"

From Eclipsepedia

Jump to: navigation, search
 
(13 intermediate revisions by one user not shown)
Line 1: Line 1:
 
<div style="margin:5px;float:right;border:1px solid #000000;padding:5px">__TOC__</div>  
 
<div style="margin:5px;float:right;border:1px solid #000000;padding:5px">__TOC__</div>  
  
=JSON Binding and Twitter=
+
=JSON Binding: Twitter Example=
 +
 
 +
This example will demonstrate using MOXy to read and write JSON.  In this example our JSON corresponds to the results of a query to get recent tweets about JAXB.  We will use the [https://dev.twitter.com/docs/api/1/get/search Twitter Search API] for this.
  
In this example our JSON corresponds to the results of a query to get recent tweets about JAXB.  We will use the [https://dev.twitter.com/docs/api/1/get/search Twitter Search API] for this.
 
  
 
==Twitter Query==
 
==Twitter Query==
Line 10: Line 11:
  
 
http://search.twitter.com/search.json?q=jaxb
 
http://search.twitter.com/search.json?q=jaxb
 +
  
 
==JSON Result==
 
==JSON Result==
  
Below is an example of the JSON returned from Twitter:
+
Below is an example excerpt of the JSON returned from Twitter:
  
 
<div style="width:850px">
 
<div style="width:850px">
Line 62: Line 64:
 
         "to_user_id_str":null
 
         "to_user_id_str":null
 
       },
 
       },
 +
      ...
 +
</source>
 +
</div>
  
 +
 +
==Domain Model==
 +
 +
MOXy leverages the same annotations used to map objects to/from XML for its JSON binding.
 +
 +
 +
'''SearchResults'''
 +
<div style="width:850px">
 +
<source lang="java">
 +
package org.example;
 +
 +
import java.util.List;
 +
 +
import javax.xml.bind.annotation.XmlElement;
 +
 +
public class SearchResults {
 +
 +
    private String query;
 +
    private float completedIn;
 +
    List<Result> results;
 +
 +
    public String getQuery() {
 +
        return query;
 +
    }
 +
 +
    public void setQuery(String query) {
 +
        this.query = query;
 +
    }
 +
 +
    @XmlElement(name="completed_in")
 +
    public float getCompletedIn() {
 +
        return completedIn;
 +
    }
 +
 +
    public void setCompletedIn(float completedIn) {
 +
        this.completedIn = completedIn;
 +
    }
 +
 +
    public List<Result> getResults() {
 +
        return results;
 +
    }
 +
 +
    public void setResults(List<Result> results) {
 +
        this.results = results;
 +
    }
 +
 +
}
 +
</source>
 +
</div>
 +
 +
 +
'''Result'''
 +
<div style="width:850px">
 +
<source lang="java">
 +
package blog.json.twitter;
 +
 +
import java.util.Date;
 +
 +
import javax.xml.bind.annotation.XmlElement;
 +
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 +
 +
public class Result {
 +
 +
    private Date createdAt;
 +
    private String fromUser;
 +
    private String text;
 +
 +
    @XmlElement(name="created_at")
 +
    @XmlJavaTypeAdapter(DateAdapter.class)
 +
    public Date getCreatedAt() {
 +
        return createdAt;
 +
    }
 +
 +
    public void setCreatedAt(Date createdAt) {
 +
        this.createdAt = createdAt;
 +
    }
 +
 +
    @XmlElement(name="from_user")
 +
    public String getFromUser() {
 +
        return fromUser;
 +
    }
 +
 +
    public void setFromUser(String fromUser) {
 +
        this.fromUser = fromUser;
 +
    }
 +
 +
    public String getText() {
 +
        return text;
 +
    }
 +
 +
    public void setText(String text) {
 +
        this.text = text;
 +
    }
 +
 +
}
 +
</source>
 +
</div>
 +
 +
 +
'''DateAdapter'''
 +
<div style="width:850px">
 +
<source lang="java">
 +
package org.example;
 +
 +
import java.text.SimpleDateFormat;
 +
import java.util.Date;
 +
 +
import javax.xml.bind.annotation.adapters.XmlAdapter;
 +
 +
public class DateAdapter extends XmlAdapter<String, Date> {
 +
 +
    private SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z");
 +
 +
    @Override
 +
    public String marshal(Date date) throws Exception {
 +
        return dateFormat.format(date);
 +
    }
 +
 +
    @Override
 +
    public Date unmarshal(String string) throws Exception {
 +
        return dateFormat.parse(string);
 +
    }
 +
 +
}
 +
</source>
 +
</div>
 +
 +
 +
==Demo==
 +
 +
The standard JAXB APIs are used the process the JSON message.  Only two properties need to be set: '''eclipselink.media.type''' to specify '''application/json''', and '''eclipselink.json.include-root''' to indicate there is no root node.  These properties are set on the Marshaller and Unmarshaller.  Since the JSON message does not contain a root node that can be used to determine the corresponding object type, we will leverage one of the Unmarshaller methods that lets us specify it.
 +
 +
<div style="width:850px">
 +
<source lang="java">
 +
package org.example;
 +
 +
import java.util.Date;
 +
import javax.xml.bind.*;
 +
import javax.xml.transform.stream.StreamSource;
 +
 +
public class Demo {
 +
 
 +
    public static void main(String[] args) throws Exception {
 +
        JAXBContext jc = JAXBContext.newInstance(SearchResults.class);
 +
 
 +
        Unmarshaller unmarshaller = jc.createUnmarshaller();
 +
        unmarshaller.setProperty("eclipselink.media-type", "application/json");
 +
        unmarshaller.setProperty("eclipselink.json.include-root", false);
 +
        StreamSource source = new StreamSource("http://search.twitter.com/search.json?q=jaxb");
 +
        JAXBElement<SearchResults> jaxbElement = unmarshaller.unmarshal(source, SearchResults.class);
 +
 
 +
        Result result = new Result();
 +
        result.setCreatedAt(new Date());
 +
        result.setFromUser("bsmith");
 +
        result.setText("You can now use EclipseLink JAXB (MOXy) with JSON :)");
 +
        jaxbElement.getValue().getResults().add(result);
 +
 
 +
        Marshaller marshaller = jc.createMarshaller();
 +
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
 +
        marshaller.setProperty("eclipselink.media-type", "application/json");
 +
        marshaller.setProperty("eclipselink.json.include-root", false);
 +
        marshaller.marshal(jaxbElement, System.out);
 +
    }
 +
 
 +
}
 +
</source>
 +
</div>
 +
 +
 +
In order to use this feature, you must use MOXy as your JAXB provider.  To enable MOXy, simply add a file named '''jaxb.properties''' in the same package as your domain classes with the following entry:
 +
 +
<div style="width:850px">
 +
<source lang="text">
 +
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
 +
</source>
 +
</div>
 +
 +
 +
==Output==
 +
 +
Below is an excerpt of the output from the Demo:
 +
 +
<div style="width:850px">
 +
<source lang="text">
 +
{
 +
  "completed_in" : 0.153,
 +
  "query" : "jaxb",
 +
  "results" : [ {
 +
      "created_at" : "Fri, 12 Aug 2011 01:14:57 +0000",
 +
      "from_user" : "stackfeed",
 +
      "text" : "How do you customise the XML output of Jersey JAXB serialization?"
 +
  }, {
 +
      "created_at" : "Fri, 12 Aug 2011 09:00:26 +0000",
 +
      "from_user" : "44aki110",
 +
      "text" : "How do you pronounce JAXB?: You know, URL is earl..."
 +
  }, {
 +
  ...
 +
  }, {
 +
      "created_at" : "Wed, 28 Mar 2012 15:56:55 -0400",
 +
      "from_user" : "bsmith",
 +
      "text" : "You can now use EclipseLink JAXB (MOXy) with JSON :)"
 +
  } ]
 
</source>
 
</source>
 
</div>
 
</div>

Latest revision as of 13:54, 18 June 2012

[edit] JSON Binding: Twitter Example

This example will demonstrate using MOXy to read and write JSON. In this example our JSON corresponds to the results of a query to get recent tweets about JAXB. We will use the Twitter Search API for this.


[edit] Twitter Query

Below is the URL corresponding to the search. We are looking for posts containing the word "jaxb", and want the result returned as JSON:

http://search.twitter.com/search.json?q=jaxb


[edit] JSON Result

Below is an example excerpt of the JSON returned from Twitter:

{
   "completed_in":0.153,
   "max_id":101941099769245696,
   "max_id_str":"101941099769245696",
   "next_page":"?page=2&max_id=101941099769245696&q=jaxb",
   "page":1,
   "query":"jaxb",
   "refresh_url":"?since_id=101941099769245696&q=jaxb",
   "results":[
      {
         "created_at":"Fri, 12 Aug 2011 09:00:26 +0000",
         "from_user":"44aki110",
         "from_user_id":92669210,
         "from_user_id_str":"92669210",
         "geo":null,
         "id":101941099769245696,
         "id_str":"101941099769245696",
         "iso_language_code":"ja",
         "metadata":{
            "result_type":"recent"
         },
         "profile_image_url":"http://a2.twimg.com/profile_images/1301749249/44aki110_normal.jpg",
         "source":"<a href="http://www.soicha.com" rel="nofollow">SOICHA</a>",
         "text":"How do you pronounce JAXB?: You know, URL is earl...",
         "to_user_id":null,
         "to_user_id_str":null
      },
      {
         "created_at":"Fri, 12 Aug 2011 01:14:57 +0000",
         "from_user":"stackfeed",
         "from_user_id":212341639,
         "from_user_id_str":"212341639",
         "geo":null,
         "id":101823955765170176,
         "id_str":"101823955765170176",
         "iso_language_code":"en",
         "metadata":{
            "result_type":"recent"
         },
         "profile_image_url":"http://a2.twimg.com/sticky/default_profile_images/default.png",
         "source":"<a href="http://twitterfeed.com" rel="nofollow">twitterfeed</a>",
         "text":"How do you customise the XML output of Jersey JAXB serialization?",
         "to_user_id":null,
         "to_user_id_str":null
      },
      ...


[edit] Domain Model

MOXy leverages the same annotations used to map objects to/from XML for its JSON binding.


SearchResults

package org.example;
 
import java.util.List;
 
import javax.xml.bind.annotation.XmlElement;
 
public class SearchResults {
 
    private String query;
    private float completedIn;
    List<Result> results;
 
    public String getQuery() {
        return query;
    }
 
    public void setQuery(String query) {
        this.query = query;
    }
 
    @XmlElement(name="completed_in")
    public float getCompletedIn() {
        return completedIn;
    }
 
    public void setCompletedIn(float completedIn) {
        this.completedIn = completedIn;
    }
 
    public List<Result> getResults() {
        return results;
    }
 
    public void setResults(List<Result> results) {
        this.results = results;
    }
 
}


Result

package blog.json.twitter;
 
import java.util.Date;
 
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 
public class Result {
 
    private Date createdAt;
    private String fromUser;
    private String text;
 
    @XmlElement(name="created_at")
    @XmlJavaTypeAdapter(DateAdapter.class)
    public Date getCreatedAt() {
        return createdAt;
    }
 
    public void setCreatedAt(Date createdAt) {
        this.createdAt = createdAt;
    }
 
    @XmlElement(name="from_user")
    public String getFromUser() {
        return fromUser;
    }
 
    public void setFromUser(String fromUser) {
        this.fromUser = fromUser;
    }
 
    public String getText() {
        return text;
    }
 
    public void setText(String text) {
        this.text = text;
    }
 
}


DateAdapter

package org.example;
 
import java.text.SimpleDateFormat;
import java.util.Date;
 
import javax.xml.bind.annotation.adapters.XmlAdapter;
 
public class DateAdapter extends XmlAdapter<String, Date> {
 
    private SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z");
 
    @Override
    public String marshal(Date date) throws Exception {
        return dateFormat.format(date);
    }
 
    @Override
    public Date unmarshal(String string) throws Exception {
        return dateFormat.parse(string);
    }
 
}


[edit] Demo

The standard JAXB APIs are used the process the JSON message. Only two properties need to be set: eclipselink.media.type to specify application/json, and eclipselink.json.include-root to indicate there is no root node. These properties are set on the Marshaller and Unmarshaller. Since the JSON message does not contain a root node that can be used to determine the corresponding object type, we will leverage one of the Unmarshaller methods that lets us specify it.

package org.example;
 
import java.util.Date; 
import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;
 
public class Demo {
 
    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(SearchResults.class);
 
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        unmarshaller.setProperty("eclipselink.media-type", "application/json");
        unmarshaller.setProperty("eclipselink.json.include-root", false);
        StreamSource source = new StreamSource("http://search.twitter.com/search.json?q=jaxb");
        JAXBElement<SearchResults> jaxbElement = unmarshaller.unmarshal(source, SearchResults.class);
 
        Result result = new Result();
        result.setCreatedAt(new Date());
        result.setFromUser("bsmith");
        result.setText("You can now use EclipseLink JAXB (MOXy) with JSON :)");
        jaxbElement.getValue().getResults().add(result);
 
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.setProperty("eclipselink.media-type", "application/json");
        marshaller.setProperty("eclipselink.json.include-root", false);
        marshaller.marshal(jaxbElement, System.out);
    }
 
}


In order to use this feature, you must use MOXy as your JAXB provider. To enable MOXy, simply add a file named jaxb.properties in the same package as your domain classes with the following entry:

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory


[edit] Output

Below is an excerpt of the output from the Demo:

{
   "completed_in" : 0.153,
   "query" : "jaxb",
   "results" : [ {
      "created_at" : "Fri, 12 Aug 2011 01:14:57 +0000",
      "from_user" : "stackfeed",
      "text" : "How do you customise the XML output of Jersey JAXB serialization?"
   }, {
      "created_at" : "Fri, 12 Aug 2011 09:00:26 +0000",
      "from_user" : "44aki110",
      "text" : "How do you pronounce JAXB?: You know, URL is earl..."
   }, {
   ...
   }, {
      "created_at" : "Wed, 28 Mar 2012 15:56:55 -0400",
      "from_user" : "bsmith",
      "text" : "You can now use EclipseLink JAXB (MOXy) with JSON :)"
   } ]