 | 级别: 中级 James Snell (jasnell@us.ibm.com), 软件工程师, IBM
2008 年 1 月 25 日 初看起来,将 Atom 文档转换为 JSON 似乎非常简单。毕竟,Atom 只是一些 XML,并且有大量 XML 和 JSON 转换工具可用。然而,Atom 格式不仅仅是 XML 元素和属性的集合。许多复杂的细节使得很难正确处理 Atom。本文将描述这些问题,并演示了一种由 Apache Abdera 项目实现的机制,该机制可以将 Atom 文档转换成 JSON 并生成易于理解、易于使用的完整内容。
在将一个 Atom 文档转换为 JSON 时,将获得大量富含信息的内容,并将其序列化为一种非常简单的形式。在难于解析和正确处理 XML 的环境中,您可以更加轻松地使用这种更简单的内容形式。这个过程面临的主要挑战是,确保重要数据和上下文不会在转换过程中丢失。以下章节将讨论转换 Atom 文档时的各个关键问题。假设读者至少对 Atom 和 JSON 有一个基本的了解。如果对它们都不熟悉,请在继续阅读之前查看一下本文末尾列出的 参考资料。
语言元数据
Atom 文档包含一个人类和计算机都能识别的混合信息集合。人类可读内容的恰当呈现,如条目标题、分类标签、链接标题、权限描述等等,依赖于一种在转换为 JSON 过程中必须正确保存的语言上下文。
xml:lang 是一种指定 Atom 文档所使用语言的机制。此属性可以出现在 Atom 文档中的任何位置,而且既可以被子元素继承,也可以被覆盖。xml:lang 属性的值是一个由 RFC 4646 定义的 “语言标记”
,名为 “Tags for Identifying
Languag”。这些标记提供关于文本编写所用语言、使用的脚本或编写系统的信息,以及地区性语言变化等。这类信息将影响用户代理呈现文本的方式。
清单 1 所示的示例 Atom 提要演示了 xml:lang 在 Atom 文档中的用法,但是该示例没有实际意义。
清单 1. 使用 xml:lang 的 Atom 提要
<feed xmlns="http://www.w3.org/2005/Atom"
xml:lang="en-US">
<title>This is the title</title>
...
<entry xml:lang="fr">
...
<category term="foo" label="bar" xml:lang="en" />
<category term="goo" label="baz" />
...
</entry>
</feed>
|
feed 元素上的 xml:lang 属性为整个文档建立默认的语言上下文。如果该元素的任何后代元素没有显式覆盖 xml:lang 属性(例如,提要的 title 元素),那么将自动继承此语言。
在 JSON 序列化过程中,可以将 xml:lang 属性转换为一个字段,从而捕获语言上下文。转换规则非常简单:当语言上下文发生改变时输出一个 lang 字段。清单 2 显示了 清单 1 中的提要的序列化过程。注意,只针对提要、条目和一级分类输出 lang 字段,标题和二级分类不会输出 lang 字段;因为后两种元素继承其父元素的语言。
清单 2. 对清单 1 中的提要进行序列化
{
"lang":"en-US",
"title":"This is the title",
"entries":[
{
"lang":"fr"
"categories":[
{
"lang":"en",
"term":"foo",
"label":"bar"
},
{
"term":"goo",
"label":"baz"
}
]
}
]
}
|
任何元素,只要其子元素或属性被认为是语言敏感 的,都可以包含 xml:lang 属性。在核心 Atom 词汇表中,这个集合包括 feed、entry、title、rights、subtitle、summary、content、category、link、author 和 contributor。
IRI 和 URI
除支持多种语言外,Atom 还支持使用国际化资源标识符(Internationalized Resource Identifier,IRI)。IRI 是一个允许包含非 ASCII 字符的 URI。
当设计一个 Atom 到 JSON 的序列化时,区分 IRI 在 Atom 文档中的两种用法非常重要。在清单 3 所示的示例中,有 4 个元素包含了 IRI。
清单 3. 包含多个国际化资源标识符的提要
<feed xmlns:a="http://www.w3.org/2005/Atom"
xml:base="http://examplé.org/foó">
...
<id>http://examplé.org/foó</id>
<link rel="self" href="" />
<link href="/blog" />
<category scheme="http://examplé.org/foó/bar" term="foo" />
...
</feed>
|
id 和 category 元素使用 IRI 作为标识符。尽管这些标识符与普通的 URL 很相似,但它们并不能被解除引用。Atom 要求按这种方式使用的 IRI 必须是绝对 IRI,而且通常把它们当作不需要 Atom 用户进行额外处理的 opaque 值。在 Atom 词汇表中,id 和 category 是惟一将 IRI 用作标识符的元素。
然而,link 元素是专门用于提供对某个其他资源的引用。href 属性用来指定一个可被解除引用的 IRI。该属性的值可以是一个相对路径
,而且必须由 Atom 用户处理并生成正确的结果。这个处理过程包括将 IRI 转换为一个等价的 URL。在核心 Atom 词汇表中,icon、logo、uri、link 和 content 元素可以包含能被解除引用的 IRI。
清单 4 显示了 id 和 category 元素的 JSON 序列化。注意,这些 IRI 是按原样复制的,没有经过额外处理。
清单 4. 清单 3 中的 id 和 category 元素的 JSON 序列化
"id":"http://examplé.org/foó"
"categories":[
{
"scheme":"http://examplé.org/foó/bar",
"term":"foo"
}
]
|
另一方面,可解除引用的 IRI,需要被解析为完全限定的绝对路径,并转换为通常能够在 JSON 中使用的 URL,清单 5 中将演示这一过程。注意,“http://xn--exampl-gva.org/fo%C3%B3” 是与 IRI “http://examplé.org/foó” 等价的 ASCII URL。
清单 5. 清单 3 中的 link 元素的 JSON 序列化
"links":[
{
"rel":"self",
"href":"http://xn--exampl-gva.org/fo%C3%B3"
},
{
"href":"http://xn--exampl-gva.org/blog"
}
]
|
应该同等对待 Atom 文档任意位置出现的可解除引用的 IRI 或 URI,特别是当它们出现在文本结构和内容的 HTML 和 XHTML 标记中时,如清单 6 所示。
清单 6. 包含相对 URI 路径的 XHTML 标记
<a:content type="xhtml">
<div>
<img src="/images/foo.jpg" />
</div>
</a:content>
|
由于 JSON 不能保持任何 Base URI 概念,所以使用 JSON 序列化的应用程序不可能正确呈现包含相对 URI 路径的标记。因此,在转换过程中对这类路径进行自动转换非常重要,如清单 7 所示。
清单 7. 清单 6 中的 XHTML 标记的 JSON 序列化
"content":{
"attributes":{
"type":"xhtml"
},
"children":[
{
"name":"img",
"attributes":{
"src":"http://example.org/images/foo.jpg"
},
"children":[]
}
]
}
|
很明显,这需要生成序列化 JSON 输出的应用程序能够正确解析 HTML 和 XHTML 标记,并挑选出其值可能是 URI 的属性。
可重复元素
Atom 词汇表中的一些元素能够在一个提要或条目中出现多次。在 JSON 序列化中,这些元素会呈现为清单 8 和 9 中演示的 Array。
清单 8. Atom feed、entry 和 source 元素可以包含多个 atom:author 元素
<author>
<name>James M Snell</name>
</author>
<author>
<name>Jane Doe</name>
</author>
|
清单 9. 清单 8 中的 author 元素的 JSON 序列化
"authors":[
{
"name":"James M Snell",
},
{
"name":"Jane Doe",
}
]
|
在 Atom 词汇表中,author、contributor、category、link 和
entry 元素都是可重复出现的。清单 10 到 13 进一步演示了将可重复出现的元素转换为 JSON 数组的过程。这些示例非常简单明了,因此不作赘述。
清单 10. 多个 Atom category 元素
<category term="foo"
scheme="http://example.org/categories/" />
<category term="bar"
scheme="http://example.org/categories/"
label="Bar" />
|
清单 11. 清单 10 中的多个 category 元素的 JSON 序列化
"categories":[
{
"term":"foo",
"scheme":"http://example.org/categories/"
},
{
"term":"bar",
"scheme":"http://example.org/categories/",
"label":"Bar"
}
]
|
清单 12. 多个 Atom link 元素
<link href="/foo"
rel="related"
title="Related Entry"
type="text/html" />
<link href="/bar"
title=”Alternate View"
type="text/html" />
|
清单 13. 清单 12 中多个 link 元素的 JSON 序列化
"links":[
{
"href":"http://example.org/foo",
"rel":"related",
"title":"Related Entry",
"type":"text/html"
},
{
"href":"http://example.com/bar",
"title":"Alternate View",
"type":"text/html"
}
]
|
日期
在 Atom 中使用 RFC 3339 指定的 ISO 8601 格式的一个子集表示日期和时间。清单 14 展示了一个 Atom updated 元素的示例。
清单 14. Atom updated 元素中的 RFC 3339 日期-时间
<updated>2007-10-14T12:12:12Z</updated>
|
根据 JSON 的数据输入模型,在序列化日期时,选择非常有限。我可以:
- 将日期转换为一个数值,表示从 1970 年 1 月 1 日 00:00:00 UTC 开始经过的秒数(例如,一个标准的 UNIX® 时间戳)
- 将日期转换为日期的 JavaScript toString 序列(例如,2007 年 10 月 21 日 星期日 12:34:28 GMT-0700 (PDT))
- 按日期在 Atom 文档中的呈现形式对其进行复制。
前两个选项可以在 JavaScript 中处理,不需要开发人员做太多的工作。也就是说,要获得正确的 JavaScript Date 对象,只需调用新的 Date(feed.updated)。但是,其缺点是,使用第一个选项会丢失与毫秒数和时区偏移有关的重要信息;如果使用第二个选项,日期的 toString 序列会因实现和地区的不同而不同。尽管使用 RFC 3339 序列需要额外的工作,但这是避免数据丢失和数据含义不明的惟一选项。
清单 15. 清单 14 中的 updated 元素的 JSON 序列化
"updated":"2007-10-14T12:12:12.000Z"
|
清单 16 中的 JavaScript 代码解析 RFC 3339 日期-时间并生成一个合适的 JavaScript date 对象。
清单 16. 解析 Atom 中使用的 RFC 3339 日期-时间的 JavaScript 代码
AtomDate = Class.create();
AtomDate.pattern = /^(\d{4})(?:-(\d{2}))?(?:-(\d{2}))?(?:[Tt] \
(\d{2}):(\d{2}):(\d{2})(?:\.(\d*))?)?([Zz])?(?:([+-])(\d{2}):(\d{2}))?$/;
AtomDate.localoffset = (new Date()).getTimezoneOffset();
AtomDate.padding = function(val,char,count) {
var value = "";
while(count > 0) {
if (val < Math.pow(10,count)) value = char + value;
count--;
}
return value + val;
}
AtomDate.parse = function(val) {
if (!val) throw "Invalid Date";
if (val instanceof Date) return val;
var m = AtomDate.pattern.exec(val);
var year = new Number(m[1]?m[1]:0);
var month = new Number(m[2]?m[2]:0);
var day = new Number(m[3]?m[3]:0);
var hour = new Number(m[4]?m[4]:0);
var minute = new Number(m[5]?m[5]:0);
var second = new Number(m[6]?m[6]:0);
var millis = new Number(m[7]?m[7]:0);
var gmt = m[8];
var dir = m[9];
var offhour = new Number(m[10]?m[10]:0);
var offmin = new Number(m[11]?m[11]:0);
if (dir && offhour && offmin) {
var offset = ((offhour * 60) + offmin);
if (dir == "+") {
minute -= offset;
} else if (dir == "-") {
minute += offset;
}
}
return new Date(Date.UTC(year,month,day,hour,minute,second,millis));
}
Object.prototype.value2date = function() {
return AtomDate.parse(this);
}
|
任何字符串,只要其值是一个 RFC 3339 日期,value2date 函数就能够获得这个值并作为一个 JavaScript Date 对象。
注意:出于格式化的目的,AtomDate.pattern 正则表达式被分解为多行。
清单 17. 使用清单 16 中的日期解析代码
document.write(m.updated.value2date());
|
文本结构
Atom 支持大量的文本和内容选项,到目前为止,这是在 JSON 序列化过程中碰到的最复杂最困难的问题。文本结构,比如 title、subtitle、summary 和 rights 元素,可以包含纯文本、转义 HTML 或 XHTML 标记;这些结构具有语言敏感性,因此必须考虑 xml:lang 属性;而且 HTML 和 XHTML 标记可以包含需要解析的相对 URI。由于 Atom content 元素支持 Base64 编码的内容、任意 XML 标记和使用 src 属性引用的外部内容,这使得序列化过程更加困难。
对 Atom 内容进行 JSON 序列化的目的是找到一种通用的表示方法,该方法能够尽可能一致地捕获这些选项。清单 18 展示了一个带有 3 种文本结构的提要示例。
清单 18. 带有 3 种不同类型的文本结构的 Atom feed 元素
<feed xmlns="http://www.w3.org/2005/Atom">
...
<title>Example Feed</title>
<subtitle type="html"><p>This is an example feed</p></subtitle>
<rights xml:lang="fr">...</right>
...
</feed>
|
title 元素为纯文本。它需要继承提要的语言上下文,否则不具备描述性。subtitle 元素包含转义的 HTML 标记。right 元素也是纯文本,但它覆盖了语言上下文。清单 19 展示了这 3 个元素的 JSON 序列化。
清单 19. 清单 18 中的文本结构的 JSON 序列化
{
"title":"Example Feed",
"subtitle":{
"attributes":{
"type":"html"
},
"children":[
{
"name":"p",
"attributes":{ },
"children":["This is an example feed" ]
}
]
},
"rights":{
"attributes":{
"lang":"fr"
},
"children":[
"..."
]
}
}
|
注意,这只是最简单的情形,title 被序列化为一个简单字符串。但是,由于 right 元素中的语言上下文时刻都会变化,所以尽管它是纯文本,也被序列化为包含两个字段(attributes 和 children)的对象。
对于 subtitle 元素,HTML 标记被解析并呈现为一种分层结构。XHTML 标记也使用相同的结构(清单 20 和 21)。
清单 20. 使用 XHTML 标记的文本结构
<subtitle type="xhtml">
<div xmlns="..."><p>This is an example feed</p></div>
</subtitle>
|
清单 21. 清单 20 中的 XHTML 标记的 JSON 序列化
"subtitle":{
"attributes":{ "type":"xhtml" },
"children":[
{
"name":"p",
"attributes":{ },
"children":["This is an example feed" ]
}
]
}
|
此结构确保以一种没有歧义的、一致的方式对纯文本和标记内容进行序列化。但是,其缺点是,与编写一个简单的 document.write(...) 或在一个 div 上设置 innerHTML 属性相比,在 Web 浏览器中显示内容要更加复杂。我们需要一种方法将解析得到的结构转换为一种易于显示的形式。
清单 22 对最初由 Sam Ruby 提供的代码进行了修改,包含 Atom 文本结构或内容元素的 JSON 序列化,并将其转换为一个字符串。
清单 22. JavaScript 将经过 JSON 序列化的文本结构重新构造为可显示的字符串值
Array.prototype.hash2value = function () {
var result = '';
for (var i=0; this.length>=i; i++) if (this[i]) result+=this[i].tag2value();
return result;
}
Object.prototype.tag2value = function () {
if (this.name) {
var result = String.fromCharCode(60) + this.name;
for (key in this.attributes) {
if (typeof(this.attributes[key]) === 'function') continue;
result += ' ' + key + '="' + this.attributes[key].toString() + '"';
}
result += '>' + this.children.hash2value();
result += String.fromCharCode(60) + '/' + this.name + '>';
return result;
} else return this.toString();
}
Object.prototype.value = function() {
if (this.children) return this.children.hash2value();
else return this.toString();
}
Array.prototype.value = function() {
var result = '';
for (var i = 0; this.length>=i; i++)
if (this[i]) result+=this[i].value();
return result;
}
|
添加到 JavaScript Array 和 Object 类的 value 函数使得可以使用 hash2value 函数,而不需要考虑某个特定对象是否被序列化为简单字符串或对象结构。
清单 23. 使用清单 22 中的 JavaScript 代码显示经过 JSON 序列化的文本
document.write(m.title.value());
document.write(m.subtitle.value());
document.write(m.rights.value());
|
使用此处提供的模型处理 atom:content 元素中的扩展内容类型与处理纯文本、HTML 或 XHTML 并无二致。清单 24 展示了 4 种经过扩展的内容示例,演示了备选的媒体类型、任意格式良好的 XML、Base64 编码的二进制数据和使用 src 属性的引用内容的用法。
清单 24. 经过扩展的内容类型示例
<content type="text/plain">This is plain text</content>
<content type="application/xml"><a xmlns="foo">b</a></content>
<content type="image/jpg">{base64 encoded data}</content>
<content type="image/jpg" src="image.jpg" />
|
清单 25 展示了这些形式的内容的 JSON 序列化。
清单 25. 清单 24 中经过扩展的内容类型的 JSON 序列化
"content":{
"attributes":{ "type":"text/plain" },
"children":["This is plain text" ]
}
"content":{
"attributes":{ "type":"application/xml" },
"children":[
{
"name":"a",
"attributes": {
"xmlns":"foo"
},
"children":["b"]
}
]
}
"content":{
"attributes":{ "type":"image/jpg" },
"children":["{base64 encoded data}" ]
}
"content":{
"attributes":{
"type":"image/jpg",
"src":"http://example.org/image.jpg"
},
"children":["" ]
}
|
扩展
将 Atom 序列化为 JSON 需要考虑的最后一个问题是,如何处理扩展。有 3 种可能的选择:
- 忽略所有扩展,而且不要将它们包含在 JSON 序列化中
- 序列化已知扩展,忽略其他所有扩展
- 序列化所有扩展
第一种选择显然是最简单的选择,但是限制了 JSON 表示的整体效用(并不一定是件坏事)。第二种选择允许对已知扩展的 JSON 序列化进行优化和简化,但是仍然限制了序列化的效用。第三种选择显著增加了序列化的总体复杂性,但是能够确保原始 Atom 文档的所有信息都能够通过 JSON 表示出来。
首先讨论如何优化已知扩展的输出。Atom Threading Extension (RFC 4685) 提供了一种方法,可以表示某个条目是另一个条目的响应。主题扩展规范明确指定了 in-reply-to 元素的属性和含义,并表示多个 in-reply-to 元素可以出现在同一个条目中。了解了这一点,就可以对 in-reply-to 元素的 JSON 表示进行优化,如清单 26 和 27 所示。
清单 26. 在 Atom 条目中使用 Atom Threading Extension
<entry>
...
<thr:in-reply-to ref="tag:example.org,2007:/foo/entries/2" />
<thr:in-reply-to ref="tag:example.org,2007:/foo/entries/3" />
...
</entry>
|
清单 27. 清单 26 中的 Atom Threading Extension 的 JSON 序列化
"inreplyto":[
{
"ref":"tag:example.org,2007:/foo/entries/2"
},
{
"ref":"tag:example.org,2007:/foo/entries/3"
}
]
|
然而,对于未知的扩展,需要使用更加详细和一般化的语法捕获所有必需细节。清单 28 展示了一个带有复杂的未知扩展元素的条目示例。
清单 28. Atom 条目中复杂的未知扩展
<entry>
...
<foo:a xmlns="..."><foo:b><foo:c d="e">f</foo:c></foo:b></foo:a>
...
</entry>
|
该扩展的序列化(清单 29)方法与由 HTML 或 XHTML 标记组成的文本的序列化方法相同。
清单 29. 对清单 28 中的扩展进行 JSON 序列化
"extensions":[
{
"name":"foo:a",
"attributes":{
"xmlns:foo":"http://example.org/unknown-markup"
},
"children":[
{
"name":"foo:b",
"attributes":{ },
"children":[
{
"name":"foo:c",
"attributes":{ "d":"e" },
"children":["f" ]
}
]
}
]
}
]
|
文档转换
现在,可以获取任何 Atom 文档并将其转换为有用的 JSON 表示。清单 30 和 31 提供了转换过程的完整演示。原始 Atom 文档包含相对 IRI、语言上下文、扩展、多种文本和内容类型等。使用从 Internet 上获得的任何 XML 和 JSON 转换器运行此文档,产生的序列化都不可避免地遇到数据丢失和/或可用性问题。
清单 30. 完整的 Atom 提要文档
<?xml version="1.0" encoding="utf-8" ?>
<a:feed xmlns:a="http://www.w3.org/2005/Atom"
xmlns:thr="http://purl.org/syndication/thread/1.0"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:foo="http://example.org/unknown-markup"
xml:lang="en-US"
xml:base="http://example.org/foo"
dir="ltr">
<a:id>tag:example.org,2007:/foo</a:id>
<a:title>Example Feed</a:title>
<a:subtitle type="html"><![CDATA[<p>This is an example feed</p>]]></a:subtitle>
<a:rights type="xhtml">
<div>
<p>Copyright © James M Snell</p>
</div>
</a:rights>
<a:author xmlns="http://www.w3.org/2005/Atom">
<name>James M Snell</name>
<email>jasnell@example.org</email>
<uri>/~jasnell</uri>
</a:author>
<a:updated>2007-10-14T12:12:12Z</a:updated>
<a:link rel="self" href="" />
<a:link href="/blog" />
<a:link rel="alternate" type="application/json" href="/blog;json" />
<a:entry xml:base="entries/1">
<a:id>tag:example.org,2007:/foo/entries/1</a:id>
<a:title type="text">Entry Number One</a:title>
<a:summary type="xhtml">
<div>
<p>This is the first entry. You can read it <a href="">here</a></p>
</div>
</a:summary>
<a:rights type="html">
<p>Copyright © James M Snell</p>
</a:rights>
<a:updated>2007-10-14T12:12:12Z</a:updated>
<a:link href="" />
<a:link rel="alternate" type="application/json" href="1;json" />
<a:link rel="replies" type="application/atom+xml"
href="1;replies" thr:count="10" />
<a:content type="xhtml">
<div>
<p>This is the content of the first entry. It contains a picture.</p>
<img src="/images/foo.jpg" />
</div>
</a:content>
<thr:in-reply-to ref="tag:example.org,2007:/foo/entries/2" />
<a:category scheme="http://example.org/categories/" term="foo"
label="test" xml:lang="en-US" />
<a:category scheme="http://example.org/categories/" term="bar"
label="essai" xml:lang="fr" />
<foo:a><foo:b><foo:c d="e">f</foo:c></foo:b></foo:a>
</a:entry>
<a:entry xml:base="entries/2" xml:lang="fr">
<a:id>tag:example.org,2007:/foo/entries/2</a:id>
<a:title type="text">La première entrée</a:title>
<a:summary type="xhtml">
<div>
<p>Il s'agit de la première entrée. Vous pouvez lire
<a href="">est ici</a></p>
</div>
</a:summary>
<a:rights type="html">
<p>Copyright © James M Snell</p>
</a:rights>
<a:updated>2007-10-14T12:12:11Z</a:updated>
<a:link href="" />
<a:link rel="alternate" type="application/json" href="2;json" />
<a:link rel="replies" type="application/atom+xml"
href="2;replies" thr:count="10" />
<a:content type="xhtml">
<div>
<p>Ceci est le contenu de la première entrée. Il contient une image.</p>
<img src="/images/foo.jpg" />
</div>
</a:content>
<thr:in-reply-to ref="tag:example.org,2007:/foo/entries/1" />
<a:category scheme="http://example.org/categories/" term="foo"
label="test" xml:lang="en-US" />
<a:category scheme="http://example.org/categories/" term="bar"
label="essai" xml:lang="fr" />
<foo:a><foo:b><foo:c d="e">f</foo:c></foo:b></foo:a>
</a:entry>
</a:feed>
|
本文描述的从 Atom 到 JSON 的序列化技术能够生成一个容易理解、易于使用而且能够避免丢失重要上下文数据的 JSON 表示。
清单 31. 对清单 30 中完整的 Atom 提要文档进行 JSON 序列化
{
"lang":"en-US",
"dir":"ltr",
"id":"tag:example.org,2007:/foo",
"title":"Example Feed",
"subtitle":{
"attributes":{
"type":"html"
},
"children":[{
"name":"p",
"attributes":{ },
"children":["This is an example feed" ]
} ] },
"rights":{
"attributes":{ "type":"xhtml" },
"children":[{
"name":"p",
"attributes":{ },
"children":["Copyright \u00a9 James M Snell" ]
} ]},
"updated":"2007-10-14T12:12:12.000Z",
"authors":[{
"name":"James M Snell",
"email":"jasnell@example.org",
"uri":"http://example.org/~jasnell"
} ],
"links":[
{
"href":"http://example.org/foo",
"rel":"self"
},
{
"href":"http://example.org/blog"
},
{
"href":"http://example.org/blog;json",
"rel":"alternate",
"type":"application/json"
} ],
"entries":[...],
"attributes":{
"xml:lang":"en-US",
"xml:base":"http://example.org/foo"
}
}
|
使用 Abdera JSON Writer
本文介绍的技术已经作为 Apache Abdera 项目的一部分实现了。清单 32 中的代码演示了 Abdera JSON Writer 的使用。如果想要尝试 Atom 到 JSON 的转换,请访问 Abdera wiki,获取关于如何下载最新开发映像的信息。
清单 32. 使用 Apache Abdera JSON Writer
Abdera abdera = new Abdera();
Entry entry = abdera.newEntry();
entry.setId("http://example.org");
entry.setTitle("Testing the JSON Writer");
entry.setUpdated(new Date());
entry.addLink("http://www.example.org");
entry.addAuthor("James Snell");
entry.setSummary("This is a test of the JSON Writer");
entry.writeTo("json", System.out);
|
结束语
将数据从一种格式转换成另一种格式总是一个很困难的任务。将 Atom 这样丰富和强大的数据格式序列化为 JSON 这类简单的基本格式,一定会面临许多问题。尽管已经有许多出色的尝试,在出现标准的转换方法之前,应用程序开发人员需要处理多种质量参差不齐的不兼容序列化方法,本文描述的技术只是其中的一种。
参考资料 学习
获得产品和技术
-
IBM 试用版软件:使用试用软件构建下一个开发项目,可直接从 developerWorks 下载获得。
讨论
关于作者  | 
|  | James Snell 是 IBM WebAhead 开发实验室的成员,主要研究前沿性软件技术的原型开发和 IBM 自己使用的标准。他的研究和开发方向涉及到当前的各种技术趋势,包括 Atom、AJAX、REST、开放源码、个人发布系统、语义 Web 和语境应用程序。他积极参与 Apache Abdera 项目,目前正在筹划创建 Atom Syndication Format 和 Atom Publishing Protocol 高性能、功能完善的实现。 |
对本文的评价
|  |