「Noah Veltman的午餐会」XML与JSON:特征大比拼

分享给朋友:

在BBC工作期间,Noah Veltman 为编辑人员和设计师们组织了一系列午餐小会。这些小型讲座的内容不是关于如何写代码或者完成某个具体项目,而是让这些非工程人员了解在新闻实践中经常会遇到的技术话题,让技术问题不再那么高深莫测。当非工程人员对基础的技术有所了解后,“这个项目要花多长时间?”、“我们如何做出这样的东西?”、“我们要如何妥协才能在技术上实现它?”如此这般的问题就会被有效率的双向对话所替代。

出于这样的目标,这个系列中将不太涉及真正的写代码的教学。但对那些想好好钻研开发的人来说,这个系列将提供非常值得尝试的努力方向。这些都是真实发生在午餐会上的讨论,所以也许变成文字后少了一些临场感,但无论是对于程序员、记者还是设计师来说,这些都仍然是很有帮助的、值得学习的材料。

Noah Veltman现任纽约WNYC电台数据新闻团队的开发人员,擅长交互图表、地图和基于数据的新闻应用开发。此前他曾获得Knight-Mozilla开放新闻奖学金并在伦敦BBC NEWS工作。数据新闻网将陆续推出Noah Veltman午餐会的其他资源。

【Noah Veltman的午餐会】系列由数据新闻网独家授权编译,更多该系列文章:
【Noah Veltman的午餐会】Excel vs. Database
【Noah Veltman的午餐会】制作在线地图
【Noah Veltman的午餐会】网页抓取
【Noah Veltman的午餐会】避免数据清理时的失误

json-xml

几乎所有主流网页API(Application Program Interface,应用程序接口)都会将数据返回成XML与JSON这两种格式中的一种。这两种格式可能会令人费解,它们与你所习惯的思考数据的方式十分不同。XMLJSON并不像电子表格。而是可以表现几乎所有种类数据的十分灵活的规格。两者都涉及套嵌(nesting),所以你可以用它们来表现拥有多个层次的复杂数据。

举个例子,你有一系列国家的数据,每一个国家包含一系列城市,每一座城市又有一系列的社区。或者想想家谱,它可以很轻易地用XML或者JSON来表现。你想要追踪每个人的一些信息(比如说,他们的生日),同时也需要追踪每个人与其他所有人的关系。每当你想要用一个单独的二维图表,来表达这种复杂的套嵌式关系时,实在是伤不起的。

关于空格:以我的经验,为了使结构更加清晰,我会在代码前面缩进,并将它们置于不同的行。但这也仅仅是为了更加清楚明了。你可以对这些空格置之不理,将所有代码都写在一条长线上,照样可以奏效。通常,当你在外部(比如通过一个API)碰到某数据,所有的代码都会压缩成一条,没有空格。这样很有效率,但不便阅读。其实你可以将数据扔到某个工具(比如这个http://jsonformatter.curiousconcept.com/)里面处理,数据会变得更具可读性。

XML基础

如果你使用过HTML,那你就能理解XML背后的原理。元素(element)是由标签(tag)定义的。每一个元素都有一个名字,且包含一个开始标签(opening tag)和一个结束标签(closing tag),它们分别用<tagname>和</tagname>来表示。两个标签之间的所有内容都属于该元素,它是任何开始标签和结束标签之间的内容的“母”元素,之间的东西都是它的孩子。旁边那些既不是母亲也不是孩子的,是它的兄弟姐妹。

在这个例子中,所选择的国家有两个城市。第一座城市有两个社区,第二座城市只有一个。目前为止这些信息并不是很有帮助,因为还没有指定我们所讨论的是哪一个国家和城市。我们可以通过在开始标签内添加属性(Attribute)来达到这个目的:

现在每一个元素都有属性了。我们知道这个国家的人口,城市的人口,所有东西的名字。我们可以随心所欲地添加属性。标签的名称告诉你元素属于哪一种类型,而属性告诉你有关它的详情

当XML中存在一系列类似的数据,你通常会看到一群“兄弟姐妹”,就像这里的两座城市,一个挨着一个:

有时你会看到这个系列嵌入了某种容器元素(container element),就像这样:

但这并不是必须的。当你有关于某元素的一个独立数据(文字,数字,日期这种),你可以把它放到属性里,也可以变成标签里的内容。这两者在很大程度上是等价的:

在创建XML文件时,有人喜欢前一种方法而有人喜欢后者,个中原因总是不尽相同。如果你使用属性这种方法,就不可以创建一个拥有同样名字的属性。属性的值应该是一些简单的文本和数,所以你无法在里面套嵌。上述的两个例子都可以表达城市的名字是“洛杉矶”,但如果这座城市隶属于一个国家,或者有超过一个的名字,这就有问题了:

可行:

不可行:

可行:

不可行:

关于自关闭标签:有时你也会看到,一些开始标签没有与之相对应的结束标签,而是在末尾处用一个斜杠代替,像这样:

这是一个简写,代表这个元素里面什么也没有。

相当于:

总结一下,在阅读一个XML文件的时候,你需要理解:

  • XML文件是元素的层级
  • 元素由开始标签、结束标签和之间所有的内容构成。标签之间可以是简单的文本和数,其他的元素,或者两者都有(反之也可)
  • 元素的开始标签也可以有格式为name=”value”的属性。所有属性的值都应该是简单的文本和数,不可以是其他的元素

关于数据类型:学习XML与JSON往往会遇到的一个问题是,怎样储存一些特殊类型的数据,比如日期或者时间。XML与JSON并没有对待这种数据的特殊方法。你将它们以文本或者数的形式存储下来,最好能以一种一致的格式,比如”10/18/2012″ 或者 “October 8, 2012″,之后再按照要求进行解析。

JSON基础

除非你有JavaScript的基础,否则相较于XML,JSON可能会更棘手一些。JSON是一种主要由数组(array)和对象(object)构成的格式。被方括号“[]”包围的叫做数组,被花括号“{}”包围的叫做对象。

数组

数组是一列有序的项,由逗号隔开,像这样:

纽约是第一个,迈阿密是最后一个。如果你不关心顺序,这样是可以的,只用记住它们的存在。数组中的项可以是一些数据(比如文本或数),但也可以是对象或者其他数组。

这一列表有两个项,第一个项是另一个列表,由三个美国城市组成;第二个项也是一个列表,由三个意大利城市组成。

先不用担心那个列表的细节,只用注意一下这是一个含有三个项的列表,每个项都是一个对象。

数组是一个列表,但它也可以只含有一个项或者零个项。这些都是完全有效的数组:

对象

对象看起来也像一列东西,但你不能把它们当成列表来看。每个项都被称为一个属性(property),拥有名称(name)与值(value)。名称都用双引号括起来,且每个名称都只能在一个对象中出现一次。他们有些类似于XML中开始标签里的属性。

可行:

不可行:

和数组一样,值也可以是简单的文本或数,但它也可以是一个数组或其他的对象。所以,为了修正上面的例子,你可以这样做:

再来两个例子:

关于属性的名称:你可以在属性名称里掺杂空格,比如“vice president”,但应该尽量避免。 “vicePresident” 或者 “vice_president”会好一些,因为这些数据如果最终会被用到代码中,空格会带来麻烦

数组是用来表现一列平级的东西(比如XML中的兄弟元素)的,而对象则是用来表现一样东西的特定细节(比如XML中元素的属性)

举个例子,我可以用对象来列举城市,但是因为每一个属性都必须有名字,我必须为每个条目指定任意一个独特的名字:

为了保证灵活性,我宁愿使用数组,那样可以更加方便地增减项。而稍后引用代码来统计列表中有多少城市,或做其他操作也会更加简便。

反之亦然。我也可以为了一列属性使用数组:

我可以使用它,只要我记得列中的第一项是城市的名字,第二项是它所在的州,第三项是城市的人口。但何必呢?用对象会是更好的选择,因为这些都属于城市独特的属性。对象具有更多的描述性,添加或删除属性会容易得多:

一旦你掌握了这对概念,JSON将会变得更有意义:

  • 数组是用来表现一列平级的东西的。它有大小和顺序,如果你需要表现某物的多个情况,数组就是你想要的
  • 对象是用来表现某事物的独特描述性细节。属性写出来像一个列表,但你不能把它们当成列表来看,而是以一个外形数据来看待

JSON完全是由这两种套嵌组成的:对象和数组。每一个对象可以有其他的对象或数组作为值。每个数组可以有其他数组或对象作为列表中的项。

这是一个数组,列表中有两个对象。每个对象都代表国家,有表示国家名称和人口的属性。它还有第三个属性——城市,它的值是一个数组。这个数组包含另外两个对象,每一个都代表一座城市,包含城市名称与人口。这看起来很令人费解,但当你绞尽脑汁理解了之后,会发现这是一种很灵活且富有逻辑的信息储存方式。

总结一下,当使用JSON的时候,你需要理解:

  • 数组是一列平级的值。这些值可以是简单的数据,也可是数组或对象
  • 对象是一组已命名的属性,用来描述某物。每个属性都有一个值,这个值可以是简单的数据,也可是数组或对象

需要思考的事情

20140411204208343

如果你可以选择将数据变成XML还是JSON格式,那就选一个你用起来更舒服的格式,除非这个数据将会被直接插入某个网页应用。如果有人要用JavaScript来处理这些数据,你就要选择JSON,因为它对JavaScript很友好。

同时要记住,通常同一组数据可以有多种完全可行的结构。想出这个数据结构的人可能有很多原因支持这么做。所以在做任何其他事情之前,你只要专注于理解数据的结构就好了。

例子:马尼拉的震撼

拳击比赛的传统中,有一样被称为“赛前特征数据大比拼”的传统,是指比较两位拳击手之间的身体特征数据。下图是1975年马尼拉之战,两位拳手Muhammad Ali 和 Joe Frazier之间的数据比较:

68747470733a2f2f7261772e6769746875622e636f6d2f76656c746d616e2f6c6561726e696e676c756e636865732f6d61737465722f786d6c6a736f6e2f696d616765732f746872696c6c61696e6d616e696c612e6a7067

我们来看一下,怎样在XML里面表示一位拳手的特征数据:

你可能想要指定一些单元以变得更有帮助:

你也可以把所有的数据以属性的方式都放进<fighter>的标签里,只要你区分了这两个胸围尺寸:

在JSON中,看起来是这样子的:

现在,我们假设你想要展示两位拳击手的信息,同时还包含比赛本身的信息:

在JSON中,它看起来是这样子的:

请注意,拳击比赛有三个属性:地点,日期和拳手。拳手的值是一个有两个项的数组。每个项都是一个对象,描述一个拳手的特征。大多数的数据都是一个数,但是,举个例子,“花名”是一个数组,因为拳击手可以有任意多个花名。如果你知道每个拳手都只有一个花名,你就没有必要把它写成数组了。

创建XMLJSON

这篇入门读物主要是为了让你大致地了解XML和JSON的结构。如果要创建XML或JSON文件,你需要对语法有更深入详细的理解。同时,如果你拥有的是列表数据(比如Excel文件),想要转换成XML或JSON格式,或者只是为了学习而想看看转换成XML或JSON是什么样子,Mr. Data Converter([http://shancarter.com/data_converter/)是一个非常好的资源。

本文译者:袁竞逐

作者简介

数据新闻网

数据新闻网以引介全球范围内最顶尖的数据新闻实践为初衷,以推动数据开放及媒体革新为宗旨,面向中国的新闻从业者、媒体管理者、新传教育者以及对传媒感兴趣的设计师、程序员,提供线上信息平台与线下交流机会。