Articles
Java Platform, Micro Edition
|
| By C. Enrique Ortiz, August 2008 |
|
| |
Choosing the right data interchange format is an important design decision when building any network-aware software. This is especially true when designing mobile and embedded applications, where attributes such as lightweight and efficient are important characteristics to consider. Such characteristics are important because they translate to lower computation requirements and use of power, potentially better performance, and lower costs of operation.
In mobile applications, developers typically rely on home-grown data-interchange formats or on the Extensible Markup Language (XML). The advantage of the former is that it can be tailored to particular situations for the purpose of maximizing performance and/or computational resources. The advantage of the latter, when used over HTTP, is that it is a de facto standard for data interchange. In addition, the text-based/human-readable representation used in XML makes it easier to debug.
Yet these two approaches also have disadvantages, one being proprietary in nature, non-standard, and potentially non-interoperable, while the other one could be considered too heavy and verbose for data representation, again this is especially true for mobile and embedded applications.
|
An alternative to consider is the JavaScript Object Notation or JSON, a lightweight data-interchange format. In this article I introduce JSON for data interchange in the Java Platform, Micro Edition (Java ME).
JSON is defined as part of JavaScript (ECMAScript) scripting language. Being native to JavaScript, JSON is ideal for browser-based applications. But JSON is not limited to JavaScript, and its lightweight characteristics make it very attractive for mobile and embedded applications in general.
JSON uses a very straightforward syntax that is based on two main data structures:
JSON is text-based, making it human-readable and great for debugging. JSON supports notation for all the basic data-types, and provides the methods to parse back and forth to Java native types. The following table summarizes JSON syntax elements:
|
Type
|
Starts with
|
Ends with
|
Contain or is...
|
Example
|
|---|---|---|---|---|
| |
||||
|
Object
|
{
|
}
|
Members
|
{...}
|
|
Member
|
|
|
Pair, other members
|
|
|
Pair
|
Name (string)
|
Value
|
Name and Value separated by ":"
|
"FirstName":"Enrique"
|
|
Name
|
The name of the attribute
|
:
|
A string
|
"username"
|
|
Value
|
:
|
The actual value
|
String, number, object, array, null, boolean (true, false)
|
"C. Enrique Ortiz", true, 01234, [...], {...}
|
|
Array
|
[
|
]
|
Elements
|
["mobile", "web", "apps"]
|
|
Element
|
|
|
Values, other elements
|
|
| |
||||
The following JSON text snippet shows the request and response for JSON-Time, a helpful web-service that returns the current time for a specified time zone. the following example is a request and response for time in the central United States:
| |
|
Request:
http://json-time.appspot.com/time.json?tz=US/Central
Response:
{
"tz": "US\/Central",
"hour": 15,
"datetime": "Tue, 05 Aug 2008 15:02:27 -0500",
"second": 27,
"error": false,
"minute": 2
}
|
The response is a simple JSON text structure, an unnamed object that contains properly escaped values, Strings, numbers, and boolean.
| |
JSON supports all basic numbers and string data types. Numbers are integer digits, fractions, or exponents, but remember that floating-point/double data types are not supported on CLDC 1.0. Strings are any Unicode character.
The following characters must be properly escaped by using the Backslash character:
\")
\\)
\/)
\b)
\f)
\n)
\r)
\t)
\u4-hex-digits)
Visit JSON.org for more information about JSON syntax.
| |
As part of the Mobile and Embedded Application Developers Project, Sun Microsystems provides an open-source (Java.net) project version of the JSON for ME Java API. This source code comes properly instrumented for conditional compilation for CLDC 1.0 vs. 1.1 (that is, support for floating point). The JSON ME source code is also available at JSON.org, but without the conditional directives.
As expected, JSON ME is a subset of the full JSON Java API. The following table summarizes the JSON Java API:
|
Package Name
|
Class
|
|---|---|
| |
|
org.json.me
|
|
org.json.me.util
|
|
| |
|
JSON and JSON ME differ internally with respect to some of the data types used (for example, JSON ME's use of
Vector and
Hashtable) and the compiler directives for conditional compilation for floating point support (CLDC 1.1). The JSON ME JAR file is around 25KB.
| |
The JSON Java API provides some convenience classes,
JSONWriter and
JSONStringer, to generate JSON text. I personally prefer using the core
JSONObject directly together with
JSONArray, however, which provide the parsing capabilities needed. Let's cover a couple of simple examples that use these aforementioned core classes to serialize and deserialize a simple
DataTypes example class to and from JSON. The following code snippet illustrates the JSON text that we will use as example:
| |
{
"datatypes": {
"aString":"C. Enrique Ortiz",
"anArray":["tech","mobile","web", "apps"],
"aInteger": 15569,
"aLong": 1234567890,
"aBoolean": true,
}
}
|
Looks simple enough, right? With JSON you can nest objects within objects, and define any data structure that you can in XML.
| |
JSONObject is the core JSON Java class to use. The class provides a number of helper methods such as methods to:
accumulate values under a key
append values to the array under a key
double
get a Java
Object, a
boolean, a
double, an
int, a
JSONArray, a
JSONObject, a
long, as well as the opposite methods to
put values of the same data types
get the field names inside a
JSONObject
get the value associated with a specific key
JSONObject
null or if there is no value
Enumeration of the keys of the
JSONObject
JSONObject
JSONArray containing the names of the elements of this
JSONObject
Enumeration of the keys of the
JSONObject
JSONArray containing the values of the members of this
JSONObject
JSONObject
The Example
DataTypes Class
The following code snippet defines the
DataTypes example Java class that contains the data types supported by JSON ME. This is the class we are going to use to illustrate how to serialize to and from JSON. Again, remember that floating-point/double is not supported on CLDC 1.0:
| |
/**
* A data types class to use as example
*/
class DataTypes {
public String aString; // a string
public String[] anArray; // an array
public int anInteger; // an integer
//public double aDouble; // double not supported on CLDC 1.0
public long aLong; // a long
public boolean aBoolean; // a boolean
/**
* An example multi-data type Class
*/
public DataTypes(
String aString,
String[] anArray,
int anInteger,
//double aDouble, // Not supported on CLDC 1.0
long aLong,
boolean aBoolean) {
this.aString = aString;
this.anArray = anArray;
this.anInteger = anInteger;
//this.aDouble = aDouble; // Not supported on CLDC 1.0
this.aLong = aLong;
this.aBoolean = aBoolean;
}
:
:
}
|
Supported data types are
String,
int,
long, and
boolean, and arrays of these aforementioned basic data types.
Serializing to JSON: Generating JSON Text
Let's now create a JSON text representation of a
DataTypes class instance. Note that while the JSON Java API provides some helper classes (
JSONWriter and
JSONStringer) that allow you to use a JSON-like syntax flow in Java, the following example uses JSONOjbect and
JSONArray directly, which are simple and effective APIs. Also, the code flow used in this approach can be easily mapped to a code flow to generate XML. The code snippet below illustrates the
toJSON() helper serialization method:
| |
/**
* Serializes this DataTypes instance
*
* @return the serialized DataTypes as JSON text
*/
public String toJSON() {
// Define an external an a nexted JSONObjects
JSONObject outer = new JSONObject();
JSONObject inner = new JSONObject();
// Now generate the JSON output
try {
outer.put("datatypes", inner); // the outer object name
inner.put("aString", aString); // a name/value pair
JSONArray ja = new JSONArray();
for (int i=0; i<anArray.length; i++) {
ja.put(anArray[i]);
}
inner.put("anArray", ja); a name/value pair
inner.put("anInteger", anInteger); a name/value pair
//inner.put("aDouble", aDouble); // Not supported on CLDC 1.0
inner.put("aLong", aLong); a name/value pair
inner.put("aBoolean", aBoolean); a name/value pair
} catch (JSONException ex) {
// ...process exception
}
return outer.toString(); // return the JSON text
}
|
Note: The use of hard-coded text literals is not a good practice, but I've used them in the example code snippets for illustration purposes.
Deserializing JSON: Initializing the Class from JSON Text
The following code snippet illustrates the helper method
fromJSON(), which deserializes an input JSON text string, and initializes the instance of the
DataType class:
| |
/**
* Initializes this instance of UserInfo and de-serializes the
* input JSON string
*
* @param ji is the input JSON string
*/
public void fromJSON(String ji) {
// First, clear the object.
aString = null;
anArray = null;
anInteger = 0;
//aDouble = 0.0; // Double not supported on CLDC 1.0
aLong = 0;
aBoolean = false;
// Now initialize from JSON text.
try {
JSONObject outer = new JSONObject(ji); // the outer objet
if (outer != null) {
// Get the inner object and parse out the data
JSONObject inner = outer.getJSONObject("datatypes");
if (inner != null) {
// Parse the name/value pairs
aString = inner.getString("aString");
JSONArray ja = inner.getJSONArray("anArray");
if (ja != null) {
anArray = new String[ja.length()];
for (int i=0; i<ja.length(); i++) {
anArray[i] = (String) ja.get(i);
}
}
anInteger = inner.getInt("anInteger");
//aDouble = inner.getDouble("aDouble");
aLong = inner.getLong("aLong");
aBoolean = inner.getBoolean("aBoolean");
}
}
} catch (Exception e) {
// ...process exception
}
}
|
Using the Serialization Methods
The following code snippet shows how to use the preceding
toJSON() and
fromJSON() JSON serialization methods:
| |
// Create an initialize instance of DataTypes
DataTypes dt = new DataTypes(
"C. Enrique Ortiz", // a String
new String[] {"tech","mobile","web", "apps"}, // an Array
15569, // an int
//0.0, // a double, not supported on CLDC 1.0
1234567890, // a long
true); // a boolean
// Covert object to JSON
String j = dt.toJSON();
System.out.println("*** toJSON: " + j);
// Initialize object from JSON
System.out.println("*** fromJSON:");
dt.fromJSON(j);
// Dump to console to see if it worked
dt.dump();
|
Following is the
dump() helper method used in the preceding code for debugging:
dump() Helper Method for Debugging
| |
/**
* Dump DataTypes for debugging
*/
public void dump() {
System.out.println(" aString: " + aString);
if (anArray != null) {
for (int i =0; i<anArray.length; i++) {
System.out.println(" tag [" + i + "]: " + anArray[i]);
}
}
System.out.println(" anInteger: " + anInteger);
//System.out.println(" aDouble: " + aDouble);
System.out.println(" aLong: " + aLong);
System.out.println(" aBoolean: " + aBoolean);
}
|
| |
In this article, I have introduced JSON for ME as an alternative to XML. JSON has lightweight characteristics that make it attractive for mobile and embedded applications. With the JSON for ME Java API (contributed by Sun Microsystems), parsing JSON text is easy. The API is small enough and provides all the functionality you need for interchanging data within your application.
| |
| |
C. Enrique Ortiz is a long time mobile technologist and blogger. He is a mobility enthusiast, practitioner and professional, with many years of experience in end-to-end mobile computing.