Using JSON with Java (and PHP)

JSON stands for JavaScript Object Notation. JSON is language independent text format which uses conventions familiar to programmers and many programming languages, therefore JSON makes an ideal data-interchange language.

JSON text is organized in key-value pairs. Brackets define whether JSON contains object or array of objects.
Following rules are key to understanding JSON:

  • objects are surrounded with curly brackets { }
  • arrays are surrounded with square brackets [ ]
  • keys and values are separated by colon :
  • key-value pairs are separated by comma ,
  • strings are surrounded with double-quotes " while numbers and booleans are not
  • all keys are strings
  • value must be object, array, string, number (int, double, exp) or one of literals: true, false, null

This is evident in the following examples.

JSON object:

{
"Person": {
"Name":"Frank",
"Age":30,
"Address": {
"Street":"SomeStreet",
"City":"Somewhereland",
"ZIP":1234
},
"IDs":[4, 13, 118, 46228]
}
}

JSON array of objects:

[
{
"fruit":"apple",
"price":3.76,
"fresh":true,
"country":"Australia"
},
{
"fruit":"lemon",
"price":4.28,
"fresh":false,
"country":null
}
]

JSON equivalents of JAVA entities:

string => java.lang.String
number => java.lang.Long or java.lang.Double
true|false => java.lang.Boolean
null => null
array => java.util.List
object => java.util.Map

Example 1: Let’s order some food!

Let’s say you are hungry and the refrigerator is empty. Outside is dark. A thunderstorm rages above your house, you can’t go out. Cell-phone’s battery is dead. What will you do?

Yes, you simply implement HTTP client in Java which will send JSON request to your Pizza Delivery Service and the delivery boy will bring you pizza (if they implemented one).

Client application will send a JSON formatted request using HTTP GET method to PHP application which will evaluate request and accept it. The response will be also provided as JSON text.

JSON request looks like this:

{
"name":"Frank",
"food":"pizza",
"quantity":3
}

The client-side code is written in Java.

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;

public class PizzaOrder {

public static void send() {

try {
// make json string, try also hamburger
String json = "{\"name\":\"Frank\",\"food\":\"pizza\",\"quantity\":3}";

// send as http get request
URL url = new URL("http://www.matjazcerkvenik.si/php/json/pizzaservice.php?order="+json);
URLConnection conn = url.openConnection();

// Get the response
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = rd.readLine()) != null) {
System.out.println(line);
}
rd.close();
} catch (Exception e) {
e.printStackTrace();
}
}

public static void main(String[] args) {
send();
}
}

The JSON formatted request for pizza is sent via HTML GET method as part of URL. The Pizza Service must accept our request, decode the JSON text, extract variables and values, do some processing and return response.

The server-side code is written in PHP (pizzaservice.php)

<?php
$order = $_GET["order"];
$obj = json_decode($order);
$name = $obj -> {"name"};
$food = $obj -> {"food"};
$quty = $obj -> {"quantity"};
if ($food == "pizza") {
$price = 4.99;
} else if ($food == "hamburger") {
$price = 3.33;
} else {
$price = 0;
}
$price = $price * $quty;
if ($price == 0) {
$status = "not-accepted";
} else {
$status = "accepted";
}
$array = array("name" => $name, "food" => $food, "quantity" => $quty, "price" => $price, "status" => $status);
echo json_encode($array);
?>

Response from pizzaservice is also formatted as JSON:

{"name":"Frank","food":"pizza","quantity":3,"price":14.97,"status":"accepted"}

Next comes parsing of the JSON String to extract values... uhhhh... You can write your own parser if you find it challenging, but why bothering writing and parsing complex JSON strings when there are plenty APIs to encode/decode JSON objects for us? APIs for many programming languages already exist, including Java, PHP, C++, Perl... Just Google after them or take a look at www.json.org.

As you noticed there is no method such as ‘sendDeliveryBoy()’ implemented on the server-side, so don’t be disappointed if your pizza never arrives. But it is good to know whether your request was accepted or not. :)

Example 2: Order food over TCP/IP Socket

As mentioned, there ale lots of APIs for parsing JSON text. In this example we will use simple-json API which is - as the name suggests - simple. You can get it here. Download the latest json-simple-x.x.jar and include it in build path of the project.

In this example we will make two Java applications: server and the client. And yes, they will be communicating with JSON. Client must generate a request for food in JSON formated text:

{
"buylist":[
{
"type":"apple",
"quantity":1.5
},
{
"type":"carrots",
"quantity":0.5
}
],
"userid":46842,
"address":"Somewhere",
"name":"Frank"
}

Send the request to server (this is client-side java code):

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.UnknownHostException;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;

@SuppressWarnings("unchecked")
public class FoodOrder {

public static InputStream instream;
public static OutputStream outstream;

public static void main(String[] args) {

try {
SocketAddress sa = new InetSocketAddress("localhost", 4444);
Socket sock = new Socket();
sock.connect(sa, 10 * 1000);
instream = sock.getInputStream();
outstream = sock.getOutputStream();

int i = 0;
byte[] b = new byte[1];
PrintWriter out = new PrintWriter(outstream, true);

String s = getJsonObject();
out.println(s);
while ((i = instream.read()) != 10) {
b[0] = (byte) i;
System.out.print(new String(b));
}
System.out.println();

instream.close();
out.close();
outstream.close();
sock.close();

} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

public static String getJsonObject() {

JSONObject apples = new JSONObject();
apples.put("type", "apple");
apples.put("quantity", new Double(2.5));

JSONObject carrots = new JSONObject();
carrots.put("type", "carrot");
carrots.put("quantity", new Double(1.1));

JSONArray buylist = new JSONArray();
buylist.add(apples);
buylist.add(carrots);

JSONObject obj = new JSONObject();
obj.put("name", "Frank");
obj.put("address", "Somewhere");
obj.put("userid", new Integer(46842));

obj.put("buylist", buylist);

System.out.println("client: " + obj);

return obj.toString();
}

}

Server (called FoodService) will accept request (JSON String) on port 4444, do some decoding using simple-json API, evaluate what is to be evaluated and return response back to the user.

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Scanner;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;

public class FoodService {

public static ServerSocket s = null;
public static Socket incoming = null;

public static void main(String[] args) {

while (true) {
try {

// establish server socket
s = new ServerSocket(4444);

// wait for incoming connection
incoming = s.accept();

InputStream inps = incoming.getInputStream();
OutputStream outs = incoming.getOutputStream();

Scanner in = new Scanner(inps);
PrintWriter out = new PrintWriter(outs, true);

boolean done = false;
while (!done && in.hasNextLine()) {

// read data from Socket
String line = in.nextLine();

if (line.trim().equalsIgnoreCase("exit")) {
done = true;
} else {
out.println("Echo: " + evaluate(line));
}

}

} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}

try {
incoming.close();
incoming = null;
s.close();
s = null;
} catch (IOException e) {
e.printStackTrace();
}
}

}

public static String evaluate(String json) {

// parse input JSON text
JSONObject obj = (JSONObject) JSONValue.parse(json);
String name = obj.get("name").toString();
String address = obj.get("address").toString();
Long userid = (Long) JSONValue.parse(obj.get("userid").toString());
ArrayList<Item> itemsList = new ArrayList<Item>();
JSONArray buylist = (JSONArray) obj.get("buylist");

for (int i = 0; i < buylist.size(); i++) {
JSONObject o = (JSONObject) buylist.get(i);
Item item = new Item();
item.type = o.get("type").toString();
item.quantity = (Double) JSONValue.parse(o.get("quantity").toString());
itemsList.add(item);
}

// calculate price
Double totalPrice = 0.0;
for (Item item : itemsList) {
totalPrice += item.getPrice();
}

// generate response
// TODO generate JSON text in the same way as in FoodOrder
return name + " " + address + " " + userid + " total price: " + totalPrice;
}

/**
* Class containing values for items on buylist
*/
public static class Item {

public String type;
public Double quantity;
private Double price;

public Double getPrice() {
if (type.equalsIgnoreCase("apple")) {
price = 2.95;
} else if (type.equalsIgnoreCase("carrot")) {
price = 1.71;
} else {
price = 0.0;

}
price = price * quantity;
return price;
}
}

}

Console output on the client-side:

Echo: Frank Somewhere 46842 total price: 9.256

Because the developer is too hungry to continue coding, the response (echo) is not formatted as JSON text. You can do this on your own for practice.