Some time ago the NOS started providing their data as open data through an API. Using this API you can get the latest news items. You can limit the results to sport news. There is also a search available and a few more categories to find news for. The API is a REST like api and can return xml as well as JSON. In this blog post I am creating an API with the Spring framework RESTTemplate.
First the basics. If you want to try these examples yourself you need to request a key. More information can be found here:
Because groovy is a very nice language to do this kind of experimentation I’ll show you de groovy code first. Just a few lines to print a JSON string:
def key = "Your Key" nos = new RESTClient("http://open.nos.nl/v1/") JSON newsItems = nos.get(path : "latest/article/key/$key/output/json/category/sport/").data print newsItems
The result is a long string. If you want to convert a string to nice formatted json check the resources for a link. The following image gives you an idea of the structure of the returned JSON:
Now let us do the same thing in java. Usually this takes much more code. To be honest, it is not at all bad if you use the RESTTemplate of the Spring framework. Have a look at the following code:
public class SearchApiUsingSpring { public static void main(String[] args) { RestTemplate restTemplate = new RestTemplate(); String result = restTemplate.getForObject("http://open.nos.nl/v1/latest/article/key/{key}/output/json/category/sport/", String.class, "YOUR KEY"); System.out.println(result); } }
Of course the result is the same, not bad is it? Just three lines of real code. Nice, but not enough for my example. Of course I want to use the result as an object. Therefore I am going to use an object mapper called Jackson. Check resources for a link. Jackson is a framework that enables us to map JSON objects to actual java objects. Based on the structure of the returned JSON I created a java object and used jackson annotations to map it to the JSON structure. The spring RESTTemplate facilitates using mappers. A Jackson mapper is available. The following code shows the improved sample.
public class SearchApiUsingSpring { public static void main(String[] args) { RestTemplate restTemplate = new RestTemplate(); LatestArticle result = restTemplate.getForObject("http://open.nos.nl/v1/latest/article/key/{key}/output/json/category/sport/", LatestArticle.class, "Your Key"); for (Article article : result.getItems().get(0)) { System.out.printf("Title : %s\n", article.getTitle()); System.out.printf("Description : %s\n", article.getDescription()); System.out.printf("Link : %s\n", article.getLink()); System.out.println("_________________________________"); } } }
Just a very small difference, besides the printing stuff. The change is the type returned by the getForObject method. Now it is not a string anymore but a LatestArticle. To be able to use Jackson you do need to create the classes with a few annotations.
@JsonIgnoreProperties(ignoreUnknown = true) public class LatestArticle { @JsonProperty("latest_article") private ArrayList<ArrayList<Article>> items = new ArrayList<ArrayList<Article>>(); // getters and setters } @JsonIgnoreProperties(ignoreUnknown = true) public class Article { private String id; private String type; private String title; private String description; private String link; // getters and setters }
I use the annotation @JsonIgnoreProperties, I do not want to break my code if a property that is available in json is not available in my java class. I’ll remove it later on when I have all the properties mapped. Why not immediately? Well I want to explain what I did with the date fields first. Mapping a date is a bit different. We do need to map the date using the specific format. I include Joda time to the path and create a synchronizer for a Joda date time object. Jackson has support for joda time out of the box. But I used a different format and therefore I had to create my own. The class Article is slightly enhanced with a DateTime property called published. I only show the setter this time. This is where we have to assign our own deserializer. The code for my deserializer is also shown.
// from Article @JsonDeserialize(using = JsonDateDeserializer.class) public void setPublished(DateTime published) { this.published = published; } public class JsonDateDeserializer extends JsonDeserializer<DateTime> { private final DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss"); @Override public DateTime deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { return formatter.parseDateTime(jp.getText()); } }
Now we can also print the published date. Be sure not to put annotations on the field and on the setter. I had the problem with the last_update, I need JsonProperty annotation. First I put it on the field, but than the JsonDeserialize was not read anymore.
That is it for now, I will write more when I am ready. Than I will also publish the code. Some of the resources that were useful to me are written down below.
Resources
http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/remoting.html#rest-resttemplate
http://jackson.codehaus.org/
http://jsonviewer.stack.hu/
http://java.dzone.com/articles/how-serialize-javautildate