使用 JSON 交换数据

Javascript对象表示法(JSON)是一个花哨的名称,其背后却是一个简单的概念:网页可以下载存储为javascript变量的数据。它在科技界引起了轰动,因为 JSON 与...相比,加载、读取和操作要容易得多 XML. 此外,解析大型 XML 文件可能会造成巨大的性能损失—— JSON 为你提供一个打包好的对象,随时可用!

还记得脚本标签吗?

在javascript中,你可以使用如下符号导入任何脚本:

    <script src="http://www.mysite.com/myscript.js"></script>

浏览器会下载该脚本并在当前页面内运行它。这就是像Adsense和 InstaCalc 这样的可嵌入小部件的工作原理。

巧妙之处在于,脚本中定义的任何变量和函数都对页面可用。如果myscript.js包含一个函数showMeTheMoney(),你的页面可以调用它(并且,可以想象,看到钱)。

这一切都很好,并且已经为人们所知一段时间了。一个很酷的用途是提供 动态数据 给一个带有编码Javascript变量的页面。如果这些变量是“对象”并且我们使用它们特殊的“表示法”来传递它们,我们就可以称这个系统为 JavaScript对象表示法。(严格来说, JSON 仅涵盖“对象”部分;可执行函数是动态javascript)。

在Javascript中,你可以像这样使用对象:

var fruit = {}; // create new obj
fruit.name = "apple"; // set properties
fruit.color = "red";

// that is old fashioned! Try my new notation:

var fancyFruit = {"name":"pear", "color": "greenish"};

Javascript有一种很好的表示法,你可以使用 "key":"value" 对来定义对象。你也可以用这种方式定义数组和函数,所以实际上你的对象更像是一个类。

那么这到底有何用呢?

到目前为止,传递脚本已经不是什么新鲜事了。但有一个想法出现了:如果你加载一个 动态生成的 脚本,而它内部包含数据会怎样?现在你可以将数据作为javascript变量访问。这是我的意思:

<script src="http://www.weathersite.com/latestweather.js"></script>
Today's weather is:
<script>
document.write(Weather.today);
</script>

看到这里发生了什么吗?我们加载这个javascript(它可以每小时由服务器更新),并访问它定义的Weather对象。可以想象,Weather.today是一个包含今天天气的字符串。实际上,我们可能会有Weather[zipcode]或者站点定义的任何格式。

很酷吧?

但为什么不是XML?

啊——有些程序员会说:“诚然,你就不能下载一个 XML 文件,然后处理并解析成JavaScript变量吗?”

当然,就像你 可以 跑马拉松或使用牙线。很多人想,有些人尝试,但不是每个人都做到了。

XML 对于某些事情来说很好,但可能相当繁琐。 JSON 非常棒,因为你可以通过一个简单无痛的过程包含数据。没有解析步骤——只需包含JavaScript文件,你就能“免费”获得变量。

此外, JSON 让网站包含 函数,可用于处理数据或处理其他任务。

一些细节(一如既往)

有多种使用 JSON (参见链接以获取代码示例来源):

  • 直接包含一个script标签(如上所述)。这意味着当浏览器遇到脚本时,其中的代码会立即执行。

    <script src="http://www.mysite.com/mydata.js"></script>
    
  • 动态加载脚本标签. 你可以向 head 添加一个JavaScript标签(来自codehouse.com):

    function dhtmlLoadScript(url)
    {
       var e = document.createElement("script");
       e.src = url;
       e.type="text/javascript";
       document.getElementsByTagName("head")[0].appendChild(e);
    }
    dhtmlLoadScript("http://www.mysite.com/mydata.js");
    
  • 使用一个 AJAX 库,如 jQuery 来访问信息:

    $.getJSON("mydata.js", function(json){
      // access data with json.fieldname
    });
    

注意:前两种方法可以从任何域加载文件;一个 AJAX 请求通常只能访问同一域上的文件。对于跨域 AJAX 请求时,你可能需要使用一个“callback=?”参数,像这样:

http://api.flickr.com/services/feeds/photos_public.gne?tags=cat&tagmode=any&format=json&jsoncallback=?

这告诉jQuery创建一个临时回调函数来处理数据,并告诉端点将 JSON 响应包装在该回调函数中(示例使用 jsoncallback=test).

安全,安全,安全

我不是网络安全专家,但我足够了解其复杂性和自己可能遗漏的地方。即使是像谷歌这样的大公司也可能 有时会遇到bug.

最安全的方法是只存储公共数据并使用 JSON. 如果你将私有数据存储在 JSON (或 XML 在这方面),存在恶意网站冒充登录用户的技术。是的,安全问题有复杂的解决方法(如双重提交cookie)。但如果你是新手(像我一样),从使用 JSON 用于你不介意公开的公共信息(如天气预报)。

回调函数

这个 JSON 数据可能不是一个原始对象;它可能是传递给回调函数的对象,例如:

specialFunction( {"name" : "Bob", "email": "[email protected]"} );

在这种情况下,脚本将运行一个名为 specialFunction 你已定义的函数,并向其传递一个包含“name”和“email”属性的匿名对象。你的 specialFunction 然后可以用这些信息做各种疯狂的事情。

这种技术本质上是一样的——谷歌最初就是通过这种方式传递你的Gmail联系人。有时你可以在 URL 你用于访问 JSON 数据时指定回调函数的名称——这取决于数据提供商。

现实示例:InstaCalc中的货币转换

我最近添加了 向InstaCalc在线计算器添加货币转换,这是一个关于导入数据的好教训:

  • 找到你的数据源。 纽约联邦银行 有一个 XML 包含货币换算数据的文件。对我来说就足够了!

  • 将数据转换为 JSON 格式。你可以将 XML JSON 使用 XSLT 转换。

  • 安装 XALAN 因此你可以进行 XSL 使用Java进行转换。典型的转换如下:

    java org.apache.xalan.xslt.Process -classpath "xalan.jar" -IN in.xml -XSL in.xslt > out.xml
    

注意Java类路径问题,我遇到了麻烦,不得不手动将xalan.jar的路径包含进来。

  • 转换 XML 将属性转换为元素。属性在各种脚本中可能难以访问, XML JSON 所以将它们做成元素。使用这个 XSL 将属性转换为元素:
 
   
    
   
   
   
     
       
         
           
             
           
         
       
       
     
   
 

然后处理 XML 文件使用 XALAN:

java org.apache.xalan.xslt.Process -classpath "xalan.jar" -IN in.xml -XSL attributes-to-elements.xslt > no-attributes.xml

最后,将 XML JSON 使用这个 XSL 变换。有几个 XML 2 JSON 样式表可供查找。

运行你的 XML 通过 XALAN 来创建最终的 JSON 数据。

java org.apache.xalan.xslt.Process -classpath "xalan.jar" -IN no-attributes.xml -XSL xml2json.xslt > currencies.json

清理你的数据。你有了原始 JSON 数据作为一个对象,但你可能希望将其包装在一个函数调用中。你可以使用一个快速的Perl脚本来包裹 myFunction( ) 以上数据,以便你的文件在执行时进行回调。

瞧!现在你有了 JSON 数据已准备好,可使用上述某种技术进行访问(查看货币 JSON 数据)。在InstaCalc中,我有一个对文件的静态引用:

  <script src="http://instacalc.com/data/currencies.json"><script>

由于银行有一些命名空间信息,我在回调函数中像这样访问变量: data["frbny:DataSet"];。当然,如何访问你的 JSON 数据的细节会因你的 XML 和所使用的具体样式表而变化。尝试一下。如果你查看原始 JSON 文件,就能看到你需要使用的字段名称。

加时赛:更新 JSON. 如果你的数据经常变化(比如汇率数据),你可以将上述步骤放入脚本中并按计划运行。下次加载你的网页时,它将获取新的 JSON 数据。

临别思考

JSON 是一种非常简单的数据交换方式——只需将其视为在程序中包含额外的JavaScript文件。了解更多请访问 json.org,学习它,喜爱它。祝你好运。

本系列其他文章

  1. Ruby on Rails 入门:我希望当初就知道的事
  2. Rails 进阶:理解模型(Model)、视图(View)和控制器(Controller)
  3. Javascript 简明而全面概述
  4. 使用 JSON 交换数据
  5. 如何为你的 Web 应用制作一个书签工具(Bookmarklet)

加入 45 万月度读者

喜欢这篇文章?还有更多内容能帮你建立持久、直观的数学理解。加入通讯以获取额外内容和最新更新。