技术开发 频道

Ajax 的 Java 对象序列化



JavaScript 对象标注

实际上,JavaScript 对象的大部分都由联合数组、数字索引数组、字符串、数字或者这些类型的嵌套组合而成。因为所有类型都可以用 JavaScript 直接声明,所以可以在一条语句中静态地定义对象图。清单 7 使用 JSON 语法声明了一个对象,并演示了如何访问这个对象。大括号表示联合数组(即对象),它的键 -值组合由逗号分隔。方括号表示数字索引数组。


清单 7. 用 JSON 在 JavaScript 中直接声明一个简单对象

            var band = {
            name: "The Beatles",
            members: [
            {
            name: "John",
            instruments: ["Vocals","Guitar","Piano"]
            },
            {
            name: "Paul",
            instruments: ["Vocals","Bass","Piano","Guitar"]
            },
            {
            name: "George",
            instruments: ["Guitar","Vocals"]
            },
            {
            name: "Ringo",
            instruments: ["Drums","Vocals"]
            }
            ]
            };
            // Interrogate the band object
            var musician = band.members[3];
            alert( musician.name
            + " played " + musician.instruments[0]
            + " with " + band.name );
            

既然 JSON 是一个有趣的语言特性,那么它对 Ajax 有什么意义呢?妙处在于可以用 JSON 在 Ajax 服务器响应中通过网络发送 JavaScript 对象图。这意味着在客户端可以避免使用笨拙的 DOM API 对 XML 进行导航 —— 只需要分析 JSON 响应,就会立即得到可以访问的 JavaScript 对象图。但是,首先需要把 JavaBean 变成 JSON。

从 Java 类产生 JSON

不同 XML 生成技术所具有的优缺点也适用于 JSON 的产生。而且可以证明,存在需要再次使用表示模板技术的情况。但是,使用 JSON 在理念上更接近于在应用层之间传递序列化的对象,而不是创建应用程序状态的视图。我将介绍如何用 org.json 这个 Java API 在 Java 类上创建 toJSONObject() 方法。然后,就可以把 JSONObject 简单地序列化成 JSON。清单 8 反映了 清单 1 讨论的 XML,显示了 Order 类的 toJSONObject() 实现。


清单 8. Order 类的 toJSONObject() 方法实现

            public JSONObject toJSONObject() {
            JSONObject json = new JSONObject();
            json.put("id",id);
            json.put("cost",getFormattedCost());
            json.put("date",date);
            JSONArray jsonItems = new JSONArray();
            for (Iterator<Item> iter =
            items.iterator() ; iter.hasNext() ; ) {
            jsonItems.put(iter.next().toJSONObject());
            }
            json.put("items",jsonItems);
            return json;
            }
            

可以看到,org.json API 非常简单。 JSONObject 代表 JavaScript 对象(即联合数组),有不同的 put() 方法,方法接受的 String 键和值是原生类型、String 类型或其他 JSON 类型。JSONArray 代表索引数组,所以它的 put() 方法只接受一个值。请注意在清单 8 中,创建 jsonItems 数组,然后再用 put() 把它附加到 json 对象上;可以用另外一种方法做这项工作,就是对每个项目调用 json.accumulate("items",iter.next().toJSONObject());accumulate() 方法与 put() 类似,区别在于它把值添加到按照键进行识别的索引数组。

清单 9 显示了如何序列化 JSONObject 并把它写入 servlet 响应。


清单 9. 从 JSONObject 生成序列化的 JSON 响应

            public void doGet(HttpServletRequest req, HttpServletResponse res)
            throws java.io.IOException, ServletException {
            String custId = req.getParameter("username");
            Customer customer = getCustomer(custId);
            res.setContentType("application/x-json");
            res.getWriter().print(customer.toJSONObject());
            }
            

可以看到,它实际上什么也没有做。在这里隐式调用的 JSONObjecttoString() 方法做了所有工作。请注意,application/x-json 内容类型还有一点不确定 —— 在编写这篇文章的时候,关于 JSON 应当属于什么 MIME 类型还没有定论。但是,目前 application/x-json 是合理的选择。清单 10 显示了这个 servlet 代码的示例响应。


清单 10. Customer bean 的 JSON 表示

            {
            "orders": [
            {
            "items": [
            {
            "price": "$49.99",
            "description": "512 Megabyte Type 1 CompactFlash card.
            Manufactured by Oolong Industries",
            "name": "Oolong 512MB CF Card",
            "id": "i-55768"
            },
            {
            "price": "$299.99",
            "description": "7.2 Megapixel digital camera featuring six
            shooting modes and 3x optical zoom. Silver.",
            "name": "Fujak Superpix72 Camera",
            "id": "i-74491"
            }
            ],
            "date": "08-26-2005",
            "cost": "$349.98",
            "id": "o-11123"
            }
            ],
            "realname": "James Hyrax",
            "username": "jimmy66"
            }
            

在客户端使用 JSON

处理的最后一步是把在客户端把 JSON 数据变成 JavaScript 对象。这可以通过对 eval() 的简单调用实现,这个函数可以即时地解释包含 JavaScript 表达式的字符串。清单 11 把 JSON 响应转变成 JavaScript 对象图,然后执行清单 5 的任务,从顾客的最后一次订单中得到第一个商品的名称。


清单 11. 评估 JSON 响应

            var jsonExpression = "(" + req.responseText + ")";
            var customer = eval(jsonExpression);
            // Find name of first item in customer's last order
            var lastOrder = customer.orders[customer.orders.length-1];
            var name = lastOrder.items[0].name;
            

比较清单 11 和 清单 5 可以发现使用 JSON 的客户端的优势。如果在 Ajax 项目中要在客户端对许多复杂的服务器响应进行导航,那么 JSON 可能适合您的需要。JSON 和 XMLHttpRequest 结合还会让 Ajax 交互看起来更像 RPC 调用而不是 SOA 请求,这对应用程序的设计可能会有意义。在下一篇文章中,我要研究的框架,就是明确地为了让 JavaScript 代码对服务器端对象进行远程方法调用而设计的。

JSON 的不足

JSON 也有它的不足。使用这里介绍的 JSON 方式,就没有办法针对每个请求对对象的序列化进行裁剪,所以不需要的字段可能经常会在网络上发送。另外,添加 toJSONObject() 方法到每个 JavaBean,可伸缩性不太好,虽然用内省和标注编写一个通用的 JavaBean 到 JSON 的序列化器可能很简单。最后,如果服务器端代码是面向服务的,没有单独针对处理 Ajax 客户请求调整过,那么由于对 XML 一致的支持,XML 会是更好的选择。

0
相关文章