Using JavaScript Object Notation (JSON) in Java ME for Data Interchange

   
By C. Enrique Ortiz, August 2008  
Contents
 
 

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.

JSON versus XML
The question of JSON versus XML is a topic left to the reader. I will say that XML purists question whether JSON is reinventing the wheel, and you can find lots of discussions on this topic by searching the web. At the end, the argument of JSON versus XML should be answered based on the run-time environment, parser availability, and integration and application requirements.
 

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:

  • Collection of name/value pairs, and
  • Order list of values.

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:

Table 1 - 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:

Listing 1 - JSON-Time HTTP Request and JSON Text Response
What about Binary Data?
JSON is a text-based data representation format, and as in all text-based formats, binary data need to be encoded as text. One approach is to convert the binary data to base 64 encoding, and another approach is to convert the binary data to other text-encoded formats, such as hex values, for example [\uDEAD, \uBEEF,...].

A better solution is to decouple the binary data via a Uniform Resource Locator (URL), where the binary data is represented or pointed to by the URL. In this approach the binary data wouldn't be embedded into the JSON text but would exist on a server on the web. This approach would allow for a separate mechanism for retrieval that can support caching and asynchronous retrieval and local storage.  
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-Supported Data Types

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:

  • Quotation mark ( \")
  • Back-slash ( \\)
  • Front-slash ( \/)
  • Backspace ( \b)
  • Form-feed ( \f)
  • New-line ( \n)
  • Carriage Return ( \r)
  • Tab ( \t)
  • Hexadecimal digits ( \u4-hex-digits)

Visit JSON.org for more information about JSON syntax.

JSON on Java ME

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:

Table 2 - JSON ME Java API
Package Name
Class
org.json.me
  • JSONArray is an ordered sequence of values
  • JSONException is error detected
  • JSONObject is an ordered collection of name/value pairs
  • JSONString is an Interface for JSON serialization
  • JSONStringer is a subclass of JSONWriter for generating JSON syntax
  • JSONTokener is a parsing utility class used by JSONObject and JSONArray
  • JSONWriter is a convenience class to generate JSON syntax
  • StringWriter is StringBuffer-based implementation of StringWriter. This a Sun Microsystems helper class, not part of the standard JSON Java API
org.json.me.util
  • XML is a helper class to generation JSON from XML
  • XMLTokener extends JSONTokener in support of XML parsing
 

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.

Using JSON

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:

Listing 2 - JSON Text 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.

The Core JSON JSONObject Class

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
  • Generate a String from a 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
  • Find if a specific key exist inside a JSONObject
  • Determine if the value associated with the key is null or if there is no value
  • Get an Enumeration of the keys of the JSONObject
  • Get the number of keys stored in the JSONObject
  • Get a JSONArray containing the names of the elements of this JSONObject
  • Generate a String from a number
  • Generate a String in double-quotes with backslash sequences in all the right places
  • Remove a name and its value, if present
  • Get an Enumeration of the keys of the JSONObject
  • Generate a JSONArray containing the values of the members of this JSONObject
  • Generate a JSON text of this 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:

Listing 3 - The DataTypes Example Class
/**
 * 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:

Listing 4 - Generating JSON Text
/**
 * 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:

Listing 5 - Initializing the Object from an Input JSON Text String
/**
 * 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:

Listing 6 - Using the 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:

Listing 7 - The 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);
}
 
Conclusion

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.

Resources
 

About C. Enrique Ortiz

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.

Rate and Review
Tell us what you think of the content of this page.
Excellent   Good   Fair   Poor  
Comments:
Your email address (no reply is possible without an address):
Sun Privacy Policy

Note: We are not able to respond to all submitted comments.