Java-Web:Exercise - Creating JSON from Java

From Juneday education
Jump to: navigation, search

Work in progress

This chapter is a work in progress. Remove this section when the page is production-ready.

Introduction

This exercise is about creating a Json document from Java. The goal is for you to read data from a database (using JDBC), create a list of Java objects, and loop through the list and create the Json document.

Objective

You will be given a database and some Java classes to read from the database and create objects. Your task is to write a program (a class with a main method) which will get the objects, loop through them and create a Json document containing the data from the objects.

The database contains data for a CV with job experiences. You should get a list of JobExperience object references, loop through the list and create a Json document containing the same data.

In this exercise, org.json will be used as the API for JSON. We'll be using android's version of the API.

The database

The database is provided for you and is an SQLite database with the following table schema:

CREATE TABLE job_experience(
  exp_id integer primary key not null,
  employer text,
  title text,
  start_date datetime,
  end_date datetime,
  description text
);

In this simple exercise, we don't focus on good database design, so we haven't normalized the data, nor have we created any constraints for e.g. the start_date or end_date columns. You are encouraged to re-design the table when you are done with the exercise if you have time over and want to practice more database stuff. But that's a task you will have to solve on your own. The focus on this exercise is to create a Json document from Java objects.

The data

The database contains rows like the following:

sqlite> .mode column
sqlite> .width 6 10 20 20 20 30
sqlite> .headers on
sqlite> SELECT * FROM job_experience;
exp_id  employer    title                 start_date            end_date              description                   
------  ----------  --------------------  --------------------  --------------------  ------------------------------
1       Yrgo        Java teacher          2017-01-01 00:00:00   2017-06-30 00:00:00   Teacher for a Java course     
2       ITHS        Database teacher      2016-01-01 00:00:00   2016-02-28 00:00:00   Teacher for a Database course
-- ... etc etc

The expected Json output format

This is an example Json document for the same data as shown above (inluding one more job):

{
  "jobs": [
    {
      "employer": "ITHS",
      "duration": {
        "start": "2016-01-01 00:00:00",
        "end": "2016-02-28 00:00:00"
      },
      "title": "Database teacher",
      "description": "Teacher for a Database course"
    },
    {
      "employer": "GU",
      "duration": {
        "start": "2016-06-01 00:00:00",
        "end": "2016-12-31 00:00:00"
      },
      "title": "Database teacher",
      "description": "Lecturer for an introductory Java course etc"
    },
    {
      "employer": "Yrgo",
      "duration": {
        "start": "2017-01-01 00:00:00",
        "end": "2017-06-30 00:00:00"
      },
      "title": "Java teacher",
      "description": "Teacher for a Java course"
    }
  ]
}

Files and directory layout

Your directory structure should look like this (when you have fetched the files for the exercise):

.
|-- android-json-6.0.1.10.jar
|-- sqlite.jar
|-- CreateCV.java
|-- cv_database_dump.sql
|-- cv.db
|-- cv.json
`-- org
    `-- yrgo
        |-- database
        |   `-- Database.java
        |-- domain
        |   `-- JobExperience.java
        `-- util
            `-- CVFetcher.java

Task 1 - Fetch the files needed to get started

Clone our github repository here or download the files from this web page using a browser. The files for these exercises here are found in the directory java-web/java-json/json-create/exercise/ .

Verify that you have the same directory structure as shown below. You should do this in a fresh, newly created directory for this exercise. You will work from "." (the current directory signified by the dot in the tree above).

Expand using link to the right to see a hint.

Using git:

$ git clone https://github.com/progund/java-web.git
$ cd java-web/java-json/json-create/exercise/

Using the zip file from DownGit:

$ mv ~/Downloads/exercise.zip .
$ unzip exercise.zip 
Archive:  exercise.zip
   creating: exercise/
   creating: exercise/org/
   creating: exercise/org/yrgo/
   creating: exercise/org/yrgo/util/
 extracting: exercise/org/yrgo/util/CVFetcher.java  
 extracting: exercise/sqlite.jar     
   creating: exercise/org/yrgo/domain/
 extracting: exercise/org/yrgo/domain/JobExperience.java  
   creating: exercise/org/yrgo/database/
 extracting: exercise/org/yrgo/database/Database.java  
 extracting: exercise/android-json-6.0.1.10.jar  
 extracting: exercise/CreateCV.java  
 extracting: exercise/cv.db          
 extracting: exercise/cv.json        
 extracting: exercise/cv_database_dump.sql
$ cd exercise

The Json file you should create, should be named CV.json and it's OK if you write it to the current directory. That means that in the CreateCV.java application, you give the file the relative path CV.json.

You will work with the file CreateCV.java, which we have created for you, but you will have to read the other files in order to understand how to solve the problem - get a List<yrgo.domain.JobExperience> from org.yrgo.util.CVFetcher, and convert it into an Json document to be written to the current directory.

Task 2 - Read and understand the code provided

Your application in CreateCV.java will need to get hold of a List<yrgo.domain.JobExperiece>. You can get this from a org.yrgo.util.CVFetcher object. Study this class and figure out how to use it.

If you want, to, you can also study how the org.yrgo.database.Database code works - it uses JDBC in order to get the data out of the database. That's also the reason for why you need to run your program with the flag -cp .:sqlite.jar (if anyone is running Windows, you should use -cp ".;sqlite.jar" - a semicolon instead of the standard colon). But the JDBC part is not essential for understanding this exercise.

You can also enter the database and add more data (more rows to the job_experience table). Study the database schema above and figure out how to add more job experiences.

In the CreateCV.java, we have provided the necessary import statements for you. You should make sure that you understand why we need the ones importing from org.yrgo.

We have also got you started by creating the basic structure for you.

You can run the program as-is to get an idea of what is left for you to do. You will need both android-json and sqlite jar files later on, so we'll provide them already to make it easier for you to use the bash history (arrow up) later.

$ javac -cp .:android-json-6.0.1.10.jar CreateCV.java && java -cp .:android-json-6.0.1.10.jar:sqlite.jar CreateCV && cat cv.json
{}

The application creates a Json document with an empty body.

Your task during the exercise, is to add Json elements to the Json thingy. You will use a CVFetcher object from a class provided in the exercise, to get a list of JobExperience references so that you can loop over all JobExperiences. In the loop you will use the current JobExperience object to get the data for the JSON document.

Task 3

Create the org.yrgo.util.CVFetcher object and get the list of JobExperiece from it. Start by printing the whole list to system out.

Expand using link to the right to see a hint.

CVFetcher fetcher = new CVFetcher();
System.out.println(fetcher.getJobs()); // Remove this printout when you see that it works!

Task 4

Create a new JSONObject called jo to represent the whole JSON document.

On the next line, create a loop around each org.yrgo.domain.JobExperience in the list you get from the fetcher. Use the for-each syntax, so that you inside the loop have a reference to one of the JobExperience objects.

Start by printing the JobExperience out on a separate line, so that you know that you are doing the loop right:

Expand using link to the right to see a hint.

      JSONObject jo = new JSONObject(); // will be used later!

      for(JobExperience job : new CVFetcher().getJobs()){
        System.out.println("Found a job! " + job);
      }

Or, in two steps (leaving out the JSONObject creation in this example):

      CVFetcher fetcher = new CVFetcher();
      for(JobExperience job : fetcher.getJobs()){
        System.out.println("Found a job! " + job);
      }

When you are sure it works, remove the printout from the loop and instead create a child JSON object called jsonJob, and one called duration .

Expand using link to the right to see a hint.

        // Inside the loop!
        JSONObject duration = new JSONObject();
        JSONObject jsonJob  = new JSONObject();

Still inside the loop, do some stuff. Use the CVFetcher job for values unless otherwise noted:

  • Put an "employer" key-value on the jsonJob object.
  • Put "start" and "stop" key-values on the duration object
  • Put "duration" key-value to jsonJob and the duration object as value
  • Put "title" key-value to jsonJob
  • Put "description" key-value to jsonJob
  • Accumulate the jsonJob object on jo with the key "jobs" (this will create a "jobs" array")

Expand using link to the right to see a hint.

      for(JobExperience job : new CVFetcher().getJobs()){
        JSONObject duration = new JSONObject();
        JSONObject jsonJob  = new JSONObject();
        jsonJob.put("employer", job.employer());
        duration.put("start"   , job.start());
        duration.put("end"   , job.end());
        jsonJob.put("duration", duration);
        jsonJob.put("title", job.title());
        jsonJob.put("description"   , job.description());
        jo.accumulate("jobs", jsonJob);
      }

Compile and run the program again and confirm that you got a dummy JSON document.

Expand using link to the right to see a hint.

It should look something like this:

$ javac -cp .:android-json-6.0.1.10.jar CreateCV.java && java -cp .:android-json-6.0.1.10.jar:sqlite.jar CreateCV && cat cv.json 
{
  "jobs": [
    {
      "employer": "ITHS",
      "duration": {
        "start": "2016-01-01 00:00:00",
        "end": "2016-02-28 00:00:00"
      },
      "title": "Database teacher",
      "description": "Teacher for a Database course"
    },
    {
      "employer": "GU",
      "duration": {
        "start": "2016-06-01 00:00:00",
        "end": "2016-12-31 00:00:00"
      },
      "title": "Database teacher",
      "description": "Lecturer for an introductory Java course etc"
    },
    {
      "employer": "Yrgo",
      "duration": {
        "start": "2017-01-01 00:00:00",
        "end": "2017-06-30 00:00:00"
      },
      "title": "Java teacher",
      "description": "Teacher for a Java course"
    }
  ]
}

Task 5 - optional

Add data (rows of data) to the database table job_experience. You can enter the database shell interactively from the terminal using sqlite3 cv.db

Expand using link to the right to see a hint.

sqlite> insert into  job_experience(employer, title, start_date, end_date, description)
        values('Some employer Inc',
               'Fancy job title',
               datetime('1971-11-24'),
               datetime('2017-01-31'),
               'Working for the man'
         );

Run the application again and verify that the new rows are converted to elements in the JSON document created by your application.

As a challenge, re-design the database to have constraints checking for valid dates. Is it possible to check that start_date comes before end_date, also? You'll have to research your database documentation for how to do that. In our small example we were using SQLite3. For SQLite3, you'd use a check constraint using comparisons between start_date and end_date.

Links

External links

Note - these exercises are using the org.json JSON library.

Source code etc

Navigation

Up next: Using a factory for creating JSON or XML!

« PreviousBook TOCNext »