法律声明
招聘信息
购买说明
云网媒体淘宝专营店
售后服务
联系我们
有啊专营店

在J2ME中使用JSON进行数据交换
发表时间:2009-1-18 17:40:47     文章来源:中国JAVA手机网
    浏览次数:1155
 
双击自动滚屏
 
    在构建任何网络感知软件时,选择正确的数据交换格式都是一项重要的设计决策。在设计移动和嵌入式应用程序时尤其如此,此时,轻量 和有效 等特性是需要考虑的重要特征。此类特征非常重要,因为它们可转化为较低的计算要求和功耗使用、可能更好的性能以及较低的运营成本。

  在移动应用程序中,开发者通常依赖于自己创建的数据交换格式或可扩展标记语言 (Extensible Markup Language, XML)。前者的优势是可以针对特定情况进行调整,从而最大限度地提高性能并且/或者最大限度地利用计算资源。当在 HTTP 上使用后者时,其优势在于它是事实上的数据交换标准。另外,在 XML 中使用的基于文本的/可读的表示形式使其比较易于调试。

  然而,这两种方法也有缺陷,第一种方法在本质上是专用的、非标准的并可能是不可互操作的,而第二种方法可能被认为对数据表示而言过于正规和繁琐,对于移动和嵌入式应用程序而言尤其如此。

  一种可以考虑的备选方法是 JavaScript Object Notation (JSON),这是一种轻量级数据交换格式。在本文中,我将介绍如何在 Java Platform, Micro Edition (Java ME) 中使用 JSON 进行数据交换。

  JSON 被定义为 JavaScript (ECMAScript) 脚本语言的一部分。由于 JSON 是 JavaScript 本身所固有的,因此对基于浏览器的应用程序而言,JSON 是一种理想的方法。但 JSON 并不仅限于 JavaScript,一般而言,它所具有的“轻量”特征使其对移动和嵌入式应用程序而言非常有吸引力。

  JSON 使用非常简单的语法,该语法基于两个主要的数据结构:

  名称/值对的集合,以及

  值的顺序列表

  JSON 是基于文本的,这使它具有很好的可读性,并且非常易于调试。JSON 支持所有基本数据类型的表示法,并且提供了将这些数据类型来回解析为 Java 本机类型的方法。下表总结了 JSON 语法元素:

  表 1 - JSON 语法元素

  
类型 起始符 终止符 包含或是... 示例
对象 { } 成员 {...}
成员 对、其他成员
名称(字符串) 由“:”分隔的名称和值 "FirstName":"Enrique"
名称 属性名 : 一个字符串 "username"
: 实际值 字符串、数字、对象、数组、null、布尔值(true、false) "C. Enrique Ortiz", true, 01234, [...], {...}
数组 [ ] 元素 ["mobile", "web", "apps"]
元素 值、其他元素

  下面的 JSON 文本片段显示了 JSON-Time 的请求和响应,这是一个有用的 Web 服务,它返回指定时区的当前时间。以下示例显示美国中部时间的请求和响应:

  清单 1 - JSON-Time HTTP 请求和 JSON 文本响应

请求:
http://json-time.appspot.com/time.json?tz=US/Central
响应:
{
 "tz": "US/Central",
 "hour": 15,
 "datetime": "Tue, 05 Aug 2008 15:02:27 -0500",
 "second": 27,
 "error": false,
 "minute": 2
}

  响应是一个简单的 JSON 文本结构,即一个包含正确转义的值、字符串、数字和布尔值的未命名对象。

  JSON 支持的数据类型

  JSON 支持所有基本数字和字符串数据类型。数字是整数数字、小数或指数,但是请记住,CLDC 1.0 中不支持浮点/双精度数据类型。字符串是任何 Unicode 字符。

  必须使用反斜杠字符正确对下列字符进行转义:

  引号 (")

  反斜杠 ()

  正斜杠 (/)

  退格 (b)

  换页 (f)

  换行 (n)

  回车 (r)

  制表 (t)

  十六进制数字 (u4-hex-digits)

  有关 JSON 语法的更多信息,请访问 JSON.org。

  Java ME 中的 JSON

  作为移动和嵌入式应用程序开发者项目的一部分,Sun Microsystems 提供了 JSON for ME Java API 的开源 (Java.net) 项目版本。此源代码适当配置了检测机制,以便针对 CLDC 1.0 或 1.1 进行条件编译(即,浮点支持)。还可以在 JSON.org 获得 JSON ME 源代码,但不包含条件指令。

  如您所料,JSON ME 是完整 JSON Java API 的子集。下表总结了 JSON Java API:

  表 2 - JSON ME Java API

  
包名称
org.json.me JSONArray 是值的有序序列

  JSONException 是检测到的错误

  JSONObject 是名称/值对的有序集合

  JSONString 是 JSON 序列化的接口

  JSONStringer 是用于生成 JSON 语法的 JSONWriter 的子类

  JSONTokener 是由 JSONObject 和 JSONArray 使用的解析工具类

  JSONWriter 是用于生成 JSON 语法的便利类

  StringWriter 是 StringWriter 的基于 StringBuffer 的实现。这是一个 Sun Microsystems 帮助类,而不是标准 JSON Java API 的一部分

org.json.me.util XML 是一个用于从 XML 生成 JSON 的帮助类

  XMLTokener 在 XML 语法解析支持方面扩展了 JSONTokener

  JSON 和 JSON ME 的内部机制有所不同,表现在下列方面:所使用的一些数据类型(例如,JSON ME 中使用的 Vector 和Hashtable),以及用于进行条件编译以支持浮点的的编译器指令 (CLDC 1.1)。JSON ME JAR 文件的大小约为 25KB。

  使用 JSON

  JSON Java API 提供了一些便利类(例如,JSONWriter 和 JSONStringer)以生成 JSON 文本。但是,我个人倾向于直接将核心 JSONObject 与 JSONArray 一起使用,这可以提供所需的解析功能。下面,我们将讨论几个简单的示例,在这些示例中,我们使用前面提到的那些核心类将一个简单的 DataTypes 示例类序列化到 JSON 以及从 JSON 反序列化这些示例类。以下代码片段演示了我们将用作示例的 JSON 文本:

  清单 2 - JSON 文本示例

{
  "datatypes": {
    "aString":"C. Enrique Ortiz",
    "anArray":["tech","mobile","web", "apps"],
    "aInteger": 15569,
    "aLong": 1234567890,
    "aBoolean": true,
  }
}

  看起来足够简单,是吗?使用 JSON 可以在对象内嵌入对象,并且可以像在 XML 中那样定义任何数据结构。

  核心 JSON JSONObject 类

  JSONObject 是可使用的核心 JSON Java 类。该类提供了许多帮助方法,例如可完成以下任务的方法:

  在键下面 accumulate 值

  向键下的数组 append 值

  从 double 类型值生成 String 类型值

  get 一个 Java Object、一个 boolean 类型值、一个 double 类型值、一个 int 类型值、一个 JSONArray 类型值、一个 JSONObject 类型值、一个 long 类型值以及 put 相同数据类型值的逆方法

  get JSONObject 内的字段名

  get 与特定键关联的值

  确定 JSONObject 内是否存在某个特定键

  确定与该键关联的值是否为 null 或者是否没有值

  获取 JSONObject 的键的 Enumeration

  获取 JSONObject 中存储的键的数量

  获取包含此 JSONObject 的元素名的 JSONArray

  从数字生成 String 类型值

  在双引号中生成一个 String,并且使反斜杠序列都处于正确的位置

  删除一个名称和它的值(如果存在)

  获取 JSONObject 的键的 Enumeration

  生成一个包含此 JSONObject 的成员值的 JSONArray

  生成此 JSONObject 的 JSON 文本

  示例 DataTypes 类

  以下代码片段定义了一个 DataTypes 示例 Java 类,该类包含 JSON ME 所支持的数据类型。我们将使用该类来说明如何序列化到 JSON 以及从 JSON 进行反序列化。同样请记住,CLDC 1.0 中不支持浮点/双精度类型。

  清单 3 - 数据类型示例类

/**
* 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;
  }
  :
  :
}

  支持的数据类型有:String、int、long、boolean 以及前面提到的这些基本数据类型的数组。

  序列化到 JSON:生成 JSON 文本

  现在,让我们创建 DataTypes 类实例的 JSON 文本表示。请注意,尽管 JSON Java API 提供了一些帮助类(JSONWriter 和 JSONStringer),以使您可以在 Java 中使用类似于 JSON 的语法流,但下面的示例直接使用 JSONOjbect 和 JSONArray 这些简单而高效的 API。另外,可以轻松地将此方法中使用的代码流映射到用于生成 XML 的代码流。下面的代码片段说明了 toJSON() 序列化帮助方法:

  清单 4 - 生成 JSON 文本

/**
* 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
}

  注意:使用硬编码文本字面值不是一种好的做法,但是,为了进行说明,我已经在该示例代码片段中使用了它们。

  反序列化 JSON:从 JSON 文本初始化类

  以下代码片段说明了帮助方法 fromJSON(),该方法反序列化一个输入 JSON 文本字符串,并且初始化 DataType 类的实例:

  清单 5 - 从输入 JSON 文本字符串初始化对象

/**
* 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
  }
}

  使用序列化方法

  以下代码片段说明如何使用前面的 toJSON() 和 fromJSON() JSON 序列化方法:

  清单 6 - 使用 JSON 序列化方法

// 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();

  以下是前面的代码中使用的用于进行调试的 dump() 帮助方法:

  清单 7 - 用于进行调试的 dump() 帮助方法

/**
* 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);
}

  结束语

  在本文中,我已经介绍了作为 XML 的备选方法的 JSON for ME。JSON 所具有的轻量特征使其对移动和嵌入式应用程序充满吸引力。使用 JSON for ME Java API(由 Sun Microsystems 贡献)可以轻松地解析 JSON 文本。该 API 足够小,并且提供了您在应用程序中交换数据所需的全部功能。

苏ICP备15033099号
 点击这里给我发消息
备案号:苏ICP备15033099号-1
版权说明 隐私保护 网站地图 支付宝 扬州市互联网报警处置中心 百度 阿里巴巴淘宝网阿里云