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

XML 数据到 JSON

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.93/5 (13投票s)

2013年6月25日

CPOL

6分钟阅读

viewsIcon

62172

如何通过 Web 服务将 SQL Server XML 数据获取到浏览器中的 JSON 对象

引言

本文介绍如何使用强大的 Newtonsoft JSON 转换器,将 SQL Server 中的 XML 数据传输到 Web 浏览器中的 JSON 对象。本文假设您熟悉 SQL Server、VB.NET、HTML 和 JavaScript 编码中的基本概念。

您需要 James Newton-King 的 Json.Net DLL。 https://nuget.net.cn/packages/newtonsoft.json/,您可以直接在 Visual Studio 的“项目/管理 NuGet 程序包...”菜单中安装。只需搜索“json.net”即可。

背景

Ajax 是从 Web 服务器检索数据并在客户端 Web 浏览器中进行处理的绝佳工具。Ajax 使您能够使用 Javascript 操作 DOM 元素,并且非常易于与 JQuery 库一起使用。最大的问题是您将传输什么类型的数据。您有很多选择。其中一些是

  • 在服务器上生成 HTML,然后直接插入到浏览器中
  • 使用 JSONP 直接从服务器检索 JavaScript
  • 生成您在客户端解析的数据集
  • 生成 XML 并使用 JQuery 解析
  • 生成 JSON 并使用 JQuery 解析

后一种方法为您在服务器和客户端都提供了极大的灵活性。它速度很快,而且编码量极少。JSON 是人类可读的文本,并且比 XML 更小、处理速度更快。一个问题是 SQL Server 目前不支持 JSON 输出。因此,您必须从数据库获取 XML 数据,或在 .NET 方法中构建数据集。在方法中构建数据集可能很麻烦,并且需要额外的处理。由于 SQL Server 对 XML 具有原生支持,因此我们在本文中选择此路径。

本文中的所有代码均与 SQL Azure 兼容。

Using the Code

首先,让我们在数据库中创建一些数据。我们将从 SQL Server 输出此数据为 XML,在 Web 服务中将其转换为 JSON,并在使用 JQuery Ajax 的 JavaScript 中进行解析。假设我们在数据库中有一个用户表

create table Users (UserID int identity(1,1) not null primary key, Username nvarchar(50) not null)
insert into Users (Username) values ('Karen')
insert into Users (Username) values ('John')
insert into Users (Username) values ('Elise')  

这是一个非常简单的数据表,但足以满足我们在本文中的目的。

SQL Server 对 XML 输出有很好的支持。我建议使用 FOR XML PATH 来格式化 XML,因为它在父/子关系方面为您提供了极大的灵活性。

使用存储过程将数据返回 Web 服务器可以使您的代码安全、快速且灵活。如果您仅使用存储过程,您可以为 SQL Server 用户 `GRANT EXECUTE`,这样没有人能够看到不来自存储过程的数据。存储过程比视图或 `SELECT` 语句更快,因为 SQL Server 会缓存存储过程的统计信息。此外,您可以更改底层视图和表,而不会影响数据库的输出。

SQL Server 的一个很好的性能提示是始终在表上创建视图,然后在存储过程中从这些视图中选择。这是 SQL Server 创建其执行计划的最佳方式。您也可以考虑使用 SQL Server 函数来返回 XML 数据。这将增加您的灵活性,并减少代码量。

要返回包含数据库中所有用户的 XML,请创建一个存储过程

 create proc GetAllUsers() as
 begin
   set nocount on;
   declare @xml XML
   SET @xml = (
        SELECT [UserID] "User/@UserID", [Username] "User/@Username" 
        FROM [Users]
        FOR XML PATH(''), TYPE, ROOT('Users')
        )
    SELECT @xml
 end   

在此过程中,我们声明了一个类型为 XML 的变量 `@xml`,这是 SQL Server 中的原生数据类型。您可以使用 `OPENXML` 命令在 SQL Server 中操作此数据类型,但这超出了本文的范围。上述过程将返回 XML

    <Users>
      <User UserID="1" Username="Karen"/>
      <User UserID="2" Username="John"/>
      <User UserID="3" Username="Elise"/>
    </Users>   

正如您可能注意到的,上面所有的 XML 节点都是自闭合的。您可能更喜欢将文本(如 `Usename`)放入节点的 `innerText` 中,这是您可以自由做的。这会对您在 JavaScript 中解析数据的方式产生轻微影响。

您可以通过在 SQL Server 查询窗口中键入“`EXECUTE GetAllUsers`”来测试上述过程。

现在我们有了数据,我们希望我们的 Web 服务器将其提供给请求的客户端。您有几种选择。简单的方法是创建一个 Web 表单,并将数据作为正常的 HTTP 响应返回,使用 `response.Write()`。我们将使用 Web 服务,因为它提供了更大的灵活性和更好的安全性。请注意,如果您使用 .NET 会话,则返回数据的函数需要 `EnableSession` 属性

 <WebMethod(EnableSession:=True)>

这将使您能够获取当前的 .NET 会话,您可以使用它来识别用户。

我们现在将创建一个名为 `MyWebService` 的 Web 服务,它将从数据库获取 XML 并向请求的客户端返回 JSON。这里有两种策略可供选择。您可以返回一个序列化为 JSON 对象的 .NET 对象,或者将 JSON 作为文本返回给 JavaScript 客户端并在那里解析。这取决于您的偏好。就个人而言,我试图避免服务器和客户端之间的强类型数据,特别是在 HTTP 环境中,并向客户端返回文本。这可能比强类型数据慢一点点,但对于客户端和服务器开发人员来说,它更灵活、更易于维护。在本文中,我们选择向客户端返回文本,并使用任何现代浏览器内置的 JSON 解析器进行解析。

如果您需要支持非常旧的浏览器,请使用像 json3 这样的第三方 JSON 解析器(用于 JavaScript)。无论如何,您都可以使用 JQuery 的 `$.parseJSON()`。

现在让我们创建我们的 Web 服务。为此,请在项目中的“`/webservices`”目录下添加一个 Web 服务“*MyWebService.asmx*”。用以下内容替换 Web 服务中的所有示例代码

Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports System.Web.Script.Services
Imports System.ComponentModel
Imports System.Xml
Imports Newtonsoft.Json

<ScriptService()> _
<WebService(Namespace:="http://www.example.com")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<ToolboxItem(False)> _
Public Class MyWebService
  Inherits WebService

  <WebMethod()> _
  Public Function GetAllUsers() as String
    Dim dc As New SqlClient.SqlCommand
    Dim con as New SqlClient.SqlConnection
    Dim mydoc as New System.Xml.XmlDocument
 
    con.ConnectionString = "<your connection string>"   
    con.Open()
    dc.Connection = con
    dc.CommandType = CommandType.StoredProcedure 
    dc.CommandText = "GetAllUsers"
    mydoc.LoadXML(dc.ExecuteScalar())
    con.Close()

    Return JsonConvert.SerializeXmlNode(mydoc, Newtonsoft.Json.Formatting.Indented)
 End Function 

End Class   

注意类上的 `ScriptService()` 属性。这将使 IIS 能够响应 Ajax 等脚本请求。您可以将命名空间替换为您想要的任何内容,例如您的网站名称。确保输入正确的数据库连接字符串。Web 服务将返回一个 JSON 对象,其中 XML 数据包含在一个 `string` 中

{d: "{
 "Users": {
 "User": [
 {
 "@UserID": "1",
 "@Username": "Karen"
 },
 {
 "@UserID": "2",
 "@Username": "John"
 },
 {
 "@UserID": "3",
 "@Username": "Elise"
 }
 ]} 
 }"
} 

这是一个只有一个条目的 JSON 对象:`d`!从数据库中获取的所有漂亮的 XML 都作为文本包装在 `d` 对象的内容中。正如您所见,此文本与 XML 一样易于阅读。一个不错但意外的功能是,XML 属性在 JSON 中的名称与您存储过程中的名称相同。

在继续之前,您的网页必须引用 JQuery 库。您可以直接通过 CDN 引用它,也可以从 http://www.jquery.com 下载。包含 JQuery 后,将以下代码粘贴到您的网页上的任何位置

<script type="text/javascript">
$(function () {  // Code in this function will run when web page is loaded in the browser.
   DisplayUsers();
});

var DisplayUsers = function() {
    var Username;

    $.ajax({
       url: "/webservices/MyWebService.asmx/GetAllUsers"
       data: "",                                             // Parameters to the web service.
       contentType: "application/json; charset=utf-8",       // Tells the web server how to respond.
       dataType: "json",                                     // Datatype JSON.
       type: "POST",                                         // HTTP method.
       async: true                                           // Asynchronous processing.
    }).done(function (rtn) { 
       var mydata = JSON.parse(rtn.d);                       // Parse the JSON text.
       if (mydata.Users) {                                   // In case XML is empty.
          $(mydata.Users.User).each(function() {             // Loop all users.
             Username = $(this).prop("@Username");
             $(document.body).append(
                $("<div>").text(Username)   // Append a DIV to the document body.
             );
          });
       }
    });
</script>  

如上所述,您可以将 `JSON.parse()` 替换为 `$.parseJSON()`。请注意,我们使用 JQuery 的 `prop()` 方法来获取 XML 属性。如果您有一个 XML 节点中的数据,您可以直接引用它。假设您有

    <Users>
      <User UserID="1"><Username>Karen</Username></User>
      <User UserID="2"><Username>John</Username></User>
      <User UserID="3"><Username>Elise</Username></User>
    </Users>       

那么您将通过以下方式获取 Elise 的名字

       this.Username;   // Instead of $(this).prop("@Username"); 

如果您有大型 XML 文档,您可能需要在 `web.config` 文件中设置 `maxJsonLength="[numberOfBytes]"`。在 `<configuration>` 部分,添加

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

希望您喜欢这篇文章,并且作为 .NET Ajax 开发人员的技能有所提高。随时发表评论或直接与我联系。谢谢!

历史

  • 首次提交
© . All rights reserved.