Wednesday, November 19, 2014

JSON/Java Binding

In this blog, I'll show you how to bind JSON data to Java objects.

Let's start with a simple books example. The following JSON file contains a list of books:

books.json:
[
{"ibsn":"978-0486400778", "author":"Mark Twain", "title":"The Adventures of Tom Sawyer"},
{"ibsn":"978-0486280615", "author":"Mark Twain", "title":"Adventures of Huckleberry Finn"}
]
To map this data to a list of Book objects, first define a Book POJO:
package com.noushin.databinding;

public class Book {
    private String ibsn;
    private String title;
    private String author;
    
    public String getIbsn() {
        return ibsn;
    }
    public void setIbsn(String ibsn) {
        this.ibsn = ibsn;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getAuthor() {
        return author;
    }
    public void setAuthor(String author) {
        this.author = author;
    }
    
    public String toString() {
        return String.format("Book ibsn: %s, title: %, author: %s ", ibsn, title, author);
    }
}

I'll be using Jackson for data binding, so add the proper dependency to your pom file:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.noushin</groupId>
    <artifactId>databinding</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>databinding</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.3.3</version>
        </dependency>
    </dependencies>
</project>

And the code to perform the transformation:
package com.noushin.databinding;

import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

public class BookService {

    public List<Book> transform(String jsonFileName) throws IOException, URISyntaxException {
        byte[] jsonData = Files.readAllBytes(Paths.get(ClassLoader.getSystemResource(jsonFileName).toURI()));
        ObjectMapper mapper = new ObjectMapper();
        List<Book> books = mapper.readValue(jsonData, new TypeReference<List<Book>>(){});
        System.out.println("Transformed " + + books.size() + " books.");
        return books;
    }
}

And finally, here is your JUnit testcase to verify the transformation:
package com.noushin.databinding;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.List;

import org.junit.Test;

import junit.framework.TestCase;

public class BookServiceTest extends TestCase {

    @Test
    public void testBookService() {
        BookService bookService = new BookService();
        try {
            List<Book> books = bookService.transform("books.json");
            assertTrue(books.get(0).getAuthor().equals("Mark Twain"));
        } 
        catch (IOException e) {
            e.printStackTrace();
        } 
        catch (URISyntaxException e) {
            e.printStackTrace();
        }
    }