json

Read JSON From a URL Example Using Data Pipeline

I have a problem. I want to read JSON from a URL. Naturally, like anybody else, I googled for some solutions. There were a lot of solutions shared in Stack Overflow and other sites. I tried some of them but I’d like to share the one where I used the Data Pipeline Java library.

1. Tools and Prerequisites

  1. Data Pipeline library
  2. Mars Eclipse

2. Project Setup

Download the Maven project example and place the Data Pipeline jar under /libs. Place the trial license file under /src/main/resources. That’s it. You should be able to run the examples driven by JUnit.

3. Read JSON From a URL

The code below is the simplest way of reading a JSON stream from a URL. Here, we are retrieving stock quotes. This API is undocumented and can change to stop working anytime without notice. Please don’t hit this API more than once a minute, or for 200 tickers, you will get your IP blocked. This is one of the methods of the ReadJsonFromUrl class.

readAJsonStream()

	public void readAJsonStream() throws Exception {

		String url = "http://www.google.com/finance/info?client=ig&q=msft,orcl,adbe";

		BufferedReader input = new BufferedReader(new InputStreamReader(new URL(url).openStream(), "UTF-8"));

		// remove preceding slashes from stream
		input.readLine();
		input.read();
		input.read();

		DataReader reader = new JsonReader(input)
				.addField("symbol", "//array/object/t")
				.addField("exchange", "//array/object/e")
				.addField("price", "//array/object/l")
				.addField("change", "//array/object/c")
				.addRecordBreak("//array/object");

		reader = new TransformingReader(reader)
				.add(new BasicFieldTransformer("price").stringToDouble())
				.add(new BasicFieldTransformer("change").stringToDouble());

		DataWriter writer = new StreamWriter(System.out);

		Job.run(reader, writer);
	}

We open the stream using InputStreamReader and pass it to BufferedReader. Somehow Google precedes the stream with a couple of slashes, so we remove them (highlighted). The JsonReader is the muscle behind reading the JSON stream which looks something like this:

JSON Stream

    [
       {
          "id":"358464",
          "t":"MSFT",
          "e":"NASDAQ",
          "l":"31.67",
          "l_cur":"31.67",
          "s":"2",
          "ltt":"4:00PM EDT",
          "lt":"Aug 1, 4:00PM EDT",
          "c":"-0.17",
          "cp":"-0.53",
          "ccol":"chr",
          "el":"31.69",
          "el_cur":"31.69",
          "elt":"Aug 1, 7:54PM EDT",
          "ec":"+0.02",
          "ecp":"0.06",
          "eccol":"chg",
          "div":"0.23",
          "yld":"2.90"
       },
       {
          "id":"419344",
          "t":"ORCL",
          "e":"NYSE",
          "l":"32.75",
          "l_cur":"32.75",
          "s":"2",
          "ltt":"4:00PM EDT",
          "lt":"Aug 1, 4:00PM EDT",
          "c":"+0.40",
          "cp":"1.24",
          "ccol":"chg",
          "el":"32.70",
          "el_cur":"32.70",
          "elt":"Aug 1, 7:15PM EDT",
          "ec":"-0.05",
          "ecp":"-0.15",
          "eccol":"chr",
          "div":"",
          "yld":"1.47"
       },
       {
          "id":"4112",
          "t":"ADBE",
          "e":"NASDAQ",
          "l":"47.70",
          "l_cur":"47.70",
          "s":"0",
          "ltt":"4:00PM EDT",
          "lt":"Aug 1, 4:00PM EDT",
          "c":"+0.42",
          "cp":"0.89",
          "ccol":"chg"
       }
    ]

What does JsonReader do? It maps the 't' attribute and its value to 'symbol' which is the stock ticker symbol. It maps the 'e' attribute and its value to 'exchange' which indicates the name of the stock exchange the public company belongs to. It maps 'l' and its value to 'price' which is the last price traded. It maps 'c' and its value to 'change' which is the percentage of the price change since closing. The addRecordBreak breaks each object into records.

The TransformingReader transforms the field name 'price' (which is the data 'l') into a Double as well as the field name 'change'. We transformed it because it was sent as a string and we know it is a number. We will do some calculations on the number.

The StreamWriter outputs the contents read by JsonReader to the console. The last line in the methods executes the read and write. Your console output should be similar to the one below:

Read JSON From a URL Output

-----------------------------------------------
0 - Record (MODIFIED) {
    0:[symbol]:STRING=[MSFT]:String
    1:[exchange]:STRING=[NASDAQ]:String
    2:[price]:DOUBLE=[72.29]:Double
    3:[change]:DOUBLE=[-0.5]:Double
}

-----------------------------------------------
1 - Record (MODIFIED) {
    0:[symbol]:STRING=[ORCL]:String
    1:[exchange]:STRING=[NYSE]:String
    2:[price]:DOUBLE=[49.02]:Double
    3:[change]:DOUBLE=[-0.07]:Double
}

-----------------------------------------------
2 - Record (MODIFIED) {
    0:[symbol]:STRING=[ADBE]:String
    1:[exchange]:STRING=[NASDAQ]:String
    2:[price]:DOUBLE=[147.8]:Double
    3:[change]:DOUBLE=[-0.01]:Double
}

-----------------------------------------------
3 records

4. Read JSON From a URL and Write to CSV

We can also write the JSON stream straight away to a CSV file while we are reading the stream. Just reminding you again, please don’t hit this API more than once a minute, or for 200 tickers, you will get your IP blocked. This is one of the methods of the ReadJsonFromUrl class.

readAJsonStreamAndWriteToCsv()

	public void readAJsonStreamAndWriteToCsv() throws Exception {

		String url = "http://www.google.com/finance/info?client=ig&q=aapl,mcd";

		BufferedReader input = new BufferedReader(new InputStreamReader(new URL(url).openStream(), "UTF-8"));

		// remove preceding slashes from stream
		input.readLine();
		input.read();
		input.read();

		DataReader reader = new JsonReader(input)
				.addField("symbol", "//array/object/t")
				.addField("exchange", "//array/object/e")
				.addField("price", "//array/object/l")
				.addField("change", "//array/object/c")
				.addRecordBreak("//array/object");

		reader = new TransformingReader(reader).add(new BasicFieldTransformer("price").stringToDouble())
				.add(new BasicFieldTransformer("change").stringToDouble());

		DataWriter writer = new CSVWriter(new File("Apple-McDonalds.txt"));

		Job.run(reader, writer);
	}

We are now reading the Apple and McDonald’s ticker symbols. Everything is the same as the readAJsonStream() method except for line number 22 (highlighted). This is now the muscle behind writing our records in CSV format. We only need to provide a filename to the CSVWriter API. So now, instead of printing it out to console, we are writing it to file. The “Apple-McDonalds.txt” contents should look like this:

Apple-McDonalds.txt

symbol,exchange,price,change
AAPL,NASDAQ,160.64,"0.56"
MCD,NYSE,155.06,"0.14"

The first line in the file are the field names followed by the records.

5. Read JSON From a URL and Transform the Data

As mentioned above, we transformed the 'price' and 'change' in order to perform calculations. The code below does exactly that.

readAJsonStreamAndTransformTheData()

	public void readAJsonStreamAndTransformTheData() throws Exception {
		
		String url = "http://www.google.com/finance/info?client=ig&q=aapl,mcd";

		BufferedReader input = new BufferedReader(new InputStreamReader(new URL(url).openStream(), "UTF-8"));

		// remove preceding slashes from stream
		input.readLine();
		input.read();
		input.read();

		DataReader reader = new JsonReader(input).addField("symbol", "//array/object/t")
				.addField("exchange", "//array/object/e")
				.addField("price", "//array/object/l")
				.addField("change", "//array/object/c")
				.addRecordBreak("//array/object");

		reader = new TransformingReader(reader)
				.add(new BasicFieldTransformer("price").stringToDouble())
				.add(new BasicFieldTransformer("change").stringToDouble());
		
		reader = new TransformingReader(reader)
                .setCondition(new FilterExpression("symbol == 'AAPL' && price < 165.00"))
                .add(new SetField("recommendation", "BUY"));

		DataWriter writer = new StreamWriter(System.out);

		Job.run(reader, writer);
	}

The code above is similar to the previous examples shown above. The difference is in line numbers 22 to 24 (highlighted). The highlighted code looks like a Java if statement. What does this do? If you can understand an if condition, I’m sure you’ll get it. If it’s an Apple stock (AAPL ticker symbol) and the price is less than 165.00 then a 'recommendation' field is added with a 'BUY' rating. If you are familiar with technical analysis in stock market trading, this could mean that the Apple stock has reached the support level which triggers a 'Buy' rating. The console output looks like this:

Console Ouput

-----------------------------------------------
0 - Record (MODIFIED) {
    0:[symbol]:STRING=[AAPL]:String
    1:[exchange]:STRING=[NASDAQ]:String
    2:[price]:DOUBLE=[161.06]:Double
    3:[change]:DOUBLE=[0.98]:Double
    4:[recommendation]:STRING=[BUY]:String
}

-----------------------------------------------
1 - Record (MODIFIED) {
    0:[symbol]:STRING=[MCD]:String
    1:[exchange]:STRING=[NYSE]:String
    2:[price]:DOUBLE=[154.92]:Double
    3:[change]:DOUBLE=[0.02]:Double
}

-----------------------------------------------
2 records

Did you notice the difference? The Apple stock record now has a 'recommendation' field. The McDonald’s stock didn’t satisfy the FilterExpression, that’s why it doesn’t have a 'recommendation' field.

6. Read JSON From a URL and Write to Database

In my opinion, this is the best part. We are able to read JSON from a URL and write it to a database as it is being read. Please don’t use the Google API in a production application. It is undocumented and you will get your IP blocked.

The code below uses MySQL but it should work on any JDBC compliant database. Did you notice that some of the field names have changed? The 'exchange' field name is now 'bourse' and 'change' is now 'price_change'.

readAJsonStreamAndWriteToDatabase()

	public void readAJsonStreamAndWriteToDatabase() throws Exception {
		
		// connect to the database
        String dbUrl = "jdbc:mysql://localhost/stocks?user=root&password=root";
        Connection connection = DriverManager.getConnection(dbUrl);
		
		String url = "http://www.google.com/finance/info?client=ig&q=mcd,aapl";

		BufferedReader input = new BufferedReader(new InputStreamReader(new URL(url).openStream(), "UTF-8"));

		// remove preceding slashes from stream
		input.readLine();
		input.read();
		input.read();

		DataReader reader = new JsonReader(input).addField("symbol", "//array/object/t")
				.addField("bourse", "//array/object/e")
				.addField("price", "//array/object/l")
				.addField("price_change", "//array/object/c")
				.addRecordBreak("//array/object");

		reader = new TransformingReader(reader)
				.add(new BasicFieldTransformer("price").stringToDouble())
				.add(new BasicFieldTransformer("price_change").stringToDouble());
		
		reader = new TransformingReader(reader)
                .setCondition(new FilterExpression("symbol != 'AAPL'"))
                .add(new SetField("recommendation", "WAIT"));
		
		reader = new TransformingReader(reader)
                .setCondition(new FilterExpression("symbol == 'AAPL' && price < 165.00"))
                .add(new SetField("recommendation", "BUY"));

		DataWriter writer = new  JdbcWriter(connection, "usa")
	            .setAutoCloseConnection(true);

		Job.run(reader, writer);
	}

First off, we need to create the database schema and the table. Here’s the SQL statement for creating the table:

SQL

CREATE TABLE `stocks`.`usa` (
  `symbol` VARCHAR(5) NOT NULL COMMENT '',
  `bourse` VARCHAR(10) NOT NULL COMMENT '',
  `price` DECIMAL(10,2) NOT NULL COMMENT '',
  `price_change` DECIMAL(10,2) NOT NULL COMMENT '',
  `recommendation` VARCHAR(5) NULL COMMENT '',
  PRIMARY KEY (`symbol`)  COMMENT '');

What did we add to our code now? It’s highlighted. We need a connection to the database. We have a new recommendation which is 'WAIT'. The JdbcWriter API takes the connection and the table name "usa" as parameters. Lastly, we set it to automatically close after writing is finished. Here’s the output:

MySQL Output

mysql> select * from usa;
+--------+--------+--------+--------------+----------------+
| symbol | bourse | price  | price_change | recommendation |
+--------+--------+--------+--------------+----------------+
| AAPL   | NASDAQ | 161.06 |         0.98 | BUY            |
| MCD    | NYSE   | 154.92 |         0.02 | WAIT           |
+--------+--------+--------+--------------+----------------+
2 rows in set (0.00 sec)

7. Summary

The Data Pipeline library does the heavy lifting for you. Reading a JSON stream is simplified and you can write the contents into many formats. It’s truly a nice tool to have in your arsenal.

8. Download the Source Code

This is an example of a Read JSON from a URL using Data Pipeline.

Download
You can download the source code of this example here: read-json-from-url-data-pipeline.zip.

Joel Patrick Llosa

I graduated from Silliman University in Dumaguete City with a degree in Bachelor of Science in Business Computer Application. I have contributed to many Java related projects at Neural Technologies Ltd., University of Southampton (iSolutions), Predictive Technologies, LLC., Confluence Service, North Concepts, Inc., NEC Telecom Software Philippines, Inc., and NEC Technologies Philippines, Inc. You can also find me in Upwork freelancing as a Java Developer.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button