最近,我一直在思考数据序列化格式这个话题。曾经无处不在的XML至少在某种程度上和在某些领域已经被JSON取代,特别是最近随着客户端上运行的Javascript代码和服务器上的Web应用程序之间的Ajax接口的出现。这是一件好事--我发现JSON比XML更友好、更理智,至少在大多数用例中是这样。
然而,一些开发人员的目标是进一步利用JSON相对于XML的简单性优势,并建议改用S表达式。甚至有人声称S-Expression是JSON的无脂替代品。这就是我要说的地方,停下来,稍等片刻。
我喜欢Lisp和Scheme,真的。然而,我坚信,虽然S-Expression是关于代码和数据等价性的一个很好的思考练习,但它并不总是JSON的有价值的替代品。这就是为什么。
考虑下面的JSON字符串,它定义了一个具有水果名称和编号对的嵌套列表:
是的,这里的标点符号较少,这很好。然而,现在假设我希望我的数据不仅仅是嵌套列表,而是水果名称到数字的映射。我也希望它是一幅高效的地图。换句话说,我想要JSON:
在Python中使用JSON处理模块读取该字符串时,我会得到一个字典。在Javascript中是一个对象,依此类推。关键是,这显然不同于仅仅是嵌套列表。在JSON中,根据定义,上面是一个无序集合,这通常意味着某种高效的关联查找(哈希表、平衡树等)。
据我所知,在不添加抽象和/或符号级别的情况下,无法将其本机表示为S表达式。
当然,Lisp-y语言有各种关联数组数据结构。例如,Common Lisp有哈希表。但是,Common Lisp哈希表的S表达式[1]表示为:
但这已经不再是一种无脂肪的语法了,尤其是对于短句来说。而且它会从一种语言变成另一种语言--Scheme有自己的关联数组实现,Clojure自己的实现,等等。
另一种选择是使用一些被接受的符号来表示S表达式中的字典。例如,在键名后面加冒号。然而,这样我们就离标准S表达式更远了。
从本质上讲,表示数据时有两种集合。有有序集合(列表、元组、数组)和无序集合(字典、关联数组、映射、散列等)。这两种语言在编程中都很重要,并且在几乎所有现代语言中都得到了本机支持和大量使用[2]。在设计数据序列化方案时,重要的是要考虑到这一区别,并且序列化格式本机支持它可能是有益的。
那么这篇文章的目的是什么呢?只是为了演示JSON与S-Expression争论的一个方面,在比较两者时并不总是考虑这一方面。这并不是说这是对S表达式的致命打击,远非如此。您的数据很可能不需要区分有序和无序集合,在这种情况下,S表达式就可以了。即使您确实需要区分,但又愿意投资于额外的抽象层,并在S表达式之上定义表示字典的符号,它们也是很好的。但是,如果您想要的东西实际上已经是标准化的,而且在许多编程语言中都是统一接受的,那么JSON可能是更好的选择。
虽然在这里和那里削减一些松散的脂肪是不错的,但实际上JSON已经足够瘦了,所以任何额外的削减都受到收益递减规律的约束。换句话说,在这里,实用性绝对胜过纯洁。
S-Expression语法没有正式说明哈希表,因此这里我指的是将由Common Lisp的Read函数转换为哈希表的文本表示形式。