65.9K
CodeProject 正在变化。 阅读更多。
Home

准备一个 JSON Web 服务并使用 JQuery 访问它

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.88/5 (48投票s)

2009年6月29日

CPOL

10分钟阅读

viewsIcon

370121

downloadIcon

9901

从 Web 服务返回 JSON 数据并使用 JQuery 访问它。

引言

我试图找出如何从 Web 服务返回 JSON 格式的数据,以及如何使用 JQuery 解析数据。我需要知道如何从 Web 服务返回 JSON 数据,以及如何从客户端使用 JQuery 解析数据。我没有找到太多详细信息或一篇可以供开发人员开始的完整文章。所以,我决定写这篇文章。当我们开发一个需要与远程计算机通信的应用程序时,需要选择并实现一种通信数据格式。对于 Web 服务,基于 XML 的 SOAP 非常普遍且被广泛接受。虽然 XML 在许多场景下都能正常工作,但它也有一些缺点,使得在某些场景下难以使用。其中一种场景是 AJAX 风格的 Web 服务,其中 XML 在客户端难以处理。此外,XML 比其对应的 JSON 表示形式更大。对于每个属性,XML 有两个标签:开始标签和结束标签。另一方面,JSON 只包含属性名一次。

什么是 JSON 格式?

JSON 是一种轻量级的数据交换格式。与 XML 类似,它人类可读、平台无关,并拥有广泛的实现。JSON 是 JavaScript 对象字面量表示法的一个子集。JSON 中的数据可以被 JavaScript 轻松解析,因此它是基于 AJAX 的 Web 应用程序的理想选择。供您参考,JSON 不支持 datetime,因为 JavaScript 没有自己的 datetime 数据类型。相反,JavaScript 中的 datetime 是一个对象。您可以 在此处 阅读有关 AJAX 中 JSON datetime 如何处理的详细信息。

为什么要关心 JSON?

假设您需要开发一个自动完成文本框,类似于 Google Suggest,如图 1 所示。当用户输入时,您需要从服务器通过 Web 服务获取数据,并在文本框下方显示。现在假设您的 Web 服务返回 XML 数据。自动完成功能的主要挑战之一是您的自动完成功能有多具交互性。如果您能节省显示建议列表的零点几秒钟,您将获得 10 倍的收益。

GoogleAutosuggest.jpg

图 1:Google 自动建议

如果 Web 服务返回 XML 数据,那么从服务器传递到客户端的数据比 JSON 格式要大。因此,使用 JSON,我们只需要传递较少的数据量。此外,客户端的 XML 解析非常麻烦且处理成本高昂。如果存在更简单的方法,我们为什么不使用它呢?假设 Web 服务返回以下 XML 数据。

<Product>
  <ProductID>1</ProductID>
  <ProductCode>p_1</ProductCode>
  <ProductName>a Product 1</ProductName>
</Product>

要在客户端解析数据,您需要使用 JavaScript 的 XML 功能。

另一方面,如果 Web 服务返回 JSON 格式,则相同的数据表示为

{"ProductID":1,"ProductName":"a Product 1"}

因此,我们可以看到 JSON 表示比其等效的 XML 表示在大小上小得多。此外,我们稍后会看到解析 JSON 格式的数据有多么容易。

要求

本文描述的代码和概念是 .NET Framework 3.5。稍后描述的 JSON 序列化器仅在 .NET Framework 3.5 中受支持。要使用随本文一起提供的附加代码,您需要 Visual Studio 2008 Service Pack 1。

Web 服务中的更改以启用 JSON

您需要在 Web 服务中进行三种类型的更改才能启用 JSON。首先,在 web.config 中注册一个 JSON 序列化器。然后,您需要为要以 JSON 表示其实例的类应用一些属性。最后,在 Web 服务方法中,您需要在将对象返回给客户端之前对其进行序列化。

1. 确保 JSON 序列化器在 web.config 中定义

如果您为 .NET Framework 3.5 配置了您的站点,那么 JSON 序列化器部分将自动添加到您的 web.config 文件中。为了确保您的 web.config 中没有缺少 ScriptJsonSerializationSection 的条目,请检查下面显示的条目是否存在于您的 web.config 中,如图 2 所示。

<section name="jsonSerialization"       
    type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, 
          Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" 
    requirePermission="false" allowDefinition="Everywhere"/>

WebConfigChange.jpg

图 2:web.config 中的 JSON 序列化器部分

默认情况下,ScriptJsonSerializer 将 JSON 字符串的长度限制为 102400(UTF-8)个字符。如果您需要更改 JSON 字符串的最大长度,请更改 JsonSerializationmaxJsonLenght 属性。在下面显示的节中,max length 已更改为 5000 个字符。

<configuration>
    <system.web.extensions>
      <scripting>
        <webServices>
          <jsonSerialization maxJsonLength="5000"/>
        </webServices>
      </scripting>
    </system.web.extensions>
</configuration>

2. 使对象可序列化

为了将我们的对象序列化为 JSON,我们将使用数据契约序列化器 System.Runtime.Serialization.Json.DataContractJsonSerializer。还有一个名为 System.Web.Script.Serialization.JavaScriptSerializer 的序列化器也可以用于 JSON 序列化,但在 .NET Framework 3.5 中被弃用,然后在 .NET Framework 3.5 SP1 中又被恢复。JavascriptSerializerDataContractJsonserializer 各有优势。JavascriptSerializer 支持匿名类型和纯字符串。而 DataContractJsonSerializer 主要用于 WCF,可处理复杂对象,并能以 UTC 格式化日期时间。在本文中,我将展示如何使用 DataContractJsonserializer。您需要为您的类应用一些属性,使其对象可以被 JSON 序列化器序列化。如果希望您的类的实例可以被 JSON 序列化器序列化,则您的类需要应用 [System.Runtime.Serialization.DataContractAttribute] 属性。此外,您不希望序列化该类的所有公共属性。只有您希望序列化的属性需要设置 [System.Runtime.Serialization.DataMemberAttribute] 属性。JSON 序列化器使用的数据契约模型是一个“选择加入”模型。将 DataMemberAttribute 应用于字段或属性会明确指定该成员值将被序列化。相比之下,BinaryFormatter(主要用于远程处理)会序列化类型的公共和私有字段,而 XMLSearilzer(在 Web 服务中用于 SOAP 格式化)仅序列化类型的公共字段和属性。因此,使用二进制格式化器或 XML 格式化器,您无法很好地控制哪些字段或属性被序列化。但是,使用 DataContractSerializer 使用的此契约模型,您可以明确指定要序列化的字段或属性。

如图 3 所示,我有一个产品类,具有三个属性:产品 ID、产品代码和产品名称,我希望此产品类的实例可以被 JSON 序列化器序列化。因此,我已将 DataContractAttribute 属性应用于 product 类。另外,我只想序列化产品 ID 和产品名称,而不是产品代码。因此,我只将 DataMemberAttribute 属性应用于产品 ID 和产品名称。

ClassChanges.jpg

图 3:类中用于序列化为 JSON 的更改

3. 准备 Web 服务方法以返回 JSON 格式的数据

Web 服务需要确保的第一件事是 Web 服务类应用了 [System.Web.Script.Services.ScriptService] 属性。此属性将确保 Web 服务可以从脚本调用。将返回 JSON 数据的 Web 服务方法需要应用 [ScriptMethod(ResponseFormat = ResponseFormat.Json)] 属性,该属性将告知客户端 Web 服务将返回 JSON 格式的数据。此外,Web 服务方法的返回类型始终是 string。

WebMethodChanges.jpg

图 4:返回 JSON 数据的 Web 方法

要以 JSON 格式化数据,您需要使用 System.Runtime.Serialization.Json.DataContractJsonSerializer。您需要将您想要序列化的对象类型传递给此 DataContractJsonSerializer。然后,创建一个内存流并将对象序列化到内存流中。最后,您需要将内存流中的字节转换为字符串并返回给客户端。在下面的代码片段中,yourObject 是您想要序列化的对象。在实际应用中,这可能是产品、客户等。

//yourobject is your actula object you want to serialize to json
DataContractJsonSerializer serializer = new 
    DataContractJsonSerializer(yourObject.GetType());
//create a memory stream
MemoryStream ms = new MemoryStream();
//serialize the object to memory stream
serializer.WriteObject(ms, yourObject);
//convert the serizlized object to string
string jsonString = Encoding.Default.GetString(ms.ToArray());
//close the memory stream
ms.Close();

使用 JQuery 调用 Web 服务

为了从客户端调用 Web 服务,我使用了 JQuery 的 ajax 方法。在 JQuery 的 ajax 方法中,您需要将请求类型设置为 post,因为 AJAX Web 服务(默认情况下)不允许通过 HTTP GET 方法调用方法 (如何启用 Web 服务中的 HTTP GET?)。供您参考,ASP.NET AJAX 控件(如 UpdatePanel)在发送异步请求时使用 HTTP POST。以下是调用 Web 服务方法的 JQuery 方法。

$.ajax({
        type: "POST",
        data: "{'prefix':''}",
        url: "/YourWebService.asmx/MethodName",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: functionToCallWhenSucceed,
        failure: funcitonToCallWhenFailed
});

在上面的代码中,‘type’ 是 HTTP POST 请求,因为 ASP.NET AJAX 的 JSON 序列化服务需要 POST 请求。‘data’ 是 Web 服务方法的参数的名称/值对。如果 Web 服务方法不接受任何参数,则需要传递空花括号。原因是 IIS 要求为所有 POST 请求提供 content length。如果 AJAX 请求中未提供‘data’,则请求的 content-length 不可用,因为 jQuery 不会自动设置该标头,除非存在 data 参数。因此,在调用无参数 Web 服务方法的情况下,‘data’ 参数应为空花括号。以下是两个 data 参数的示例。第一个用于调用不接受任何参数的 Web 服务方法。第二个用于调用接受两个参数的 Web 服务方法:SiteNamePostedDate

data: “{}”
data: ”{‘SiteName’:’CodeProject’,’PostedDate’:’1 jan 2009’}”

‘url’ 是您的 Web 服务名称,然后是方法名称。代码段中的‘contentType’ 和‘dataType’设置为 JSON 格式。JQuery ajax 方法调用中的‘success’和‘failure’属性是当 ajax 调用分别成功或失败时将被调用的两个函数名称。方法(在成功或失败时将被调用)将只有一个参数,该参数在成功时是响应,在失败时是错误消息。方法将类似于

function ajaxCallSucceed(response) {

}

function ajaxCallFailed(error) {

}

当 Web 服务调用成功时,将调用您的 ajaxCallSucceed 方法。然后,您可以按如下方式解析响应。要将 JSON 文本转换为对象,您可以使用 eval() 函数。eval() 调用 JavaScript 编译器。由于 JSON 是 JavaScript 的一个完整子集,因此编译器将正确解析文本并生成对象结构。以下代码假设响应是 JSON 格式的产品集合。

function ajaxCallSucceed(response) {

    var products = eval('(' + response.d + ')');

    for (var i = 0; i < products.length; i++) {
        //do something
    }
}

结果可以在响应对象的‘d’属性中找到。额外的括号用于使 eval 无条件地将源输入视为表达式。eval() 函数会评估一个字符串并将其执行,就好像它是脚本代码一样。因此,它可以编译任何 JavaScript 程序;这就是为什么在源受信任时应该使用 eval()。另一种选择是 JSON 解析器,它只识别 JSON 文本。

如何使用代码?

随此帖子附带的代码中有一个名为 JsonWebService.asmx 的 Web 服务。该 Web 服务只有一个名为 GetProductsJson 的 Web 方法。此方法接受一个名为 prefix 的参数。如果 prefix 不为空,则该方法以 JSON 格式返回名称以该前缀开头的前十种产品。如果 prefix 为空,则它只以 JSON 格式返回十种产品。这里,App_Code 中的 ProductFacade.cs 文件充当业务层,用于返回产品。但这里没有使用数据库;相反,它通过使用 for 循环创建了十种产品。

结论

JSON 轻量且易于使用。因此,我们可以在 AJAX/异步 Web 应用程序中轻松使用此格式。例如,我们可以在 ICallback、Page Methods 和 Web 服务中使用此格式。我们甚至可以在 XMLHttp 请求中使用此格式。

© . All rights reserved.