也是昨天有人问我关于解析xml的东西,他们用的xml主要是在两个系统之间作为配置文件传递信息,然后就有了这篇关于内容的序列化的文章。

序列化具体指什么东西呢?借用人家的定义吧:

Serialization is the process of taking objects and converting their state information into a form that can be stored or transported

不过相信很多会java的人看到Serialization的时候就知道这东西的用处了,因为java中就提供了对象序列化的方法,即java.io.Serializable,“一个类,如果要使其对象可以被串行化,必须实现Serializable接口”,在每本java的教程里都会讲到。同样,python中也有序列化的方法——Pickle,还有go语言的bson……本文不会谈论许多,主要是谈比较通用的三个:xml,json,msgpack。

xml

还是先看定义:

Extensible Markup Language (XML) is a markup language that defines a set of rules for encoding documents in a format that is both human-readable and machine-readable

所以xml的定义里并没有Serialization,但 documents in a form that is machine-readable 就已经足够让他作为数据序列化的工具了。

上最简单的例子,用xml表示一个blog的信息:

<?xml version="1.0"?>
<blog>
    <author>fyz</author>
    <title lang='en'>Serialization</title>
    <tag>code</tag>
    <year>2013</year>
    <brief>test content</brief>
</blog>

而因为xml的human-readable特性,所以我们可以很轻松的明白这个文档的意思,而通过程序我们也可以轻松获得文档里的每个信息。用python为例解析xml:

1
2
3
4
5
6
7
8
9
10
11
from xml.etree import ElementTree

doc = "<?xml version='1.0' ?><blog><author>fyz</author><title lang='en'>sss</title></blog>"
a = ElementTree.fromstring(doc)
a.getchildren()                  # 获得子节点 *[<Element 'author' at 0x1991810>, <Element 'title' at 0x1991950>]*
a.getchildren()[0].tag           # 获得标签  *author*   
a.getchildren()[0].text          # 获取内容 *fyz*
a.getchildren()[1].tag           # *title*
a.getchildren()[1].get('lang')   # 获取属性 *en*
a.insert(2,a.getchildren()[0])   # 添加子节点
ElementTree.tostring(a)          # 生成xml字符串  *<?xml version='1.0' ?><blog><author>fyz</author><author>fyz</author><title lang='en'>sss</title></blog>*

总结xml的话,我们可以感觉它的表现能力很不错,而且树形结构的层次性也很强,但不可否认的是它太繁琐了。其实为何要用<attr>xxx</attr>这种方式来表示呢?attr=xxx不也可以,如果非说这样添加属性不方便,那也可以将value部分换成hash表,同样可以表现,所以接下来我们要说的就是json了。

json

先上定义:

Json is a text-based open standard designed for human-readable data interchange

相信只要学过javascript的人都不会不知道json,也是,json的全称就是javascript object notation,是Douglas大叔为了表示javascript对象弄出来的。虽说是为javascript创造的,可是不妨碍它成为流行于当世的序列化工具,谁让dict+array的表现能力这么强呢。所以还是上面的blog信息,用json的话就简单多了:

1
2
3
4
5
6
7
8
9
10
11
12
    javascript:
    {
        "blog" : {
            "author" : "fyz",
            "title" : {"lang":"en","text":"Serialization"},
            "tag" : "code",
            "year" : 2013,
            "brief" : "test content"
        }
    }
    转换成json就是这样:
    '{"blog": {"year": 2013, "title": {"lang": "en", "text": "Serialization"}, "tag": "code", "brief": "test content", "author": "fyz"}}'

总结json,那就是它作为数据格式的确不错,但如果要传输的话,就显得太臃肿了,首先是空格太多,对每个字符串都要用引号标记,其次是对数字的处理很不友好,直接将数字转换成字符串,这些都是很浪费空间的,那么如何避免这些弊端呢?可以想象得到,引入类型系统,对javascript object中所有可能出现的类型做标记,主要是dict,array,string,number,那么就不需要再用空格、引号……来区分信息了,以此来改善长度太长的问题,这样就引出了msgpack了。

msgpack

依旧定义走起:

MessagePack is an efficient binary serialization format. It lets you exchange data among multiple languages like JSON

其实从定义我们就可以知道它是什么意思了,这是一个2进制的json。在具体处理过程中,msgpack为不同长度的number、dict、array分开处理,以节省空间。那么我们如何表示上面的blog信息呢?还是找spec吧!对于上面的blog信息,需要的规则有一下几个:

save an unsigned 16-bit big-endian integer in 3 bytes.
+--------+--------+--------+
|  0xcd  |XXXXXXXX|XXXXXXXX|
+--------+--------+--------+

save raw bytes up to 31 bytes.
+--------+--------
|101XXXXX|...N bytes
+--------+--------

save a map up to 15 elements.
+--------+--------
|1000XXXX|...N*2 objects
+--------+--------

所以生成的blog信息就是这样的:

0x81blog0x850xa4year0xcd0x07dd0xa5title0x820xa4lang0xa2en0xa4text0xadSerialization0xa3tag0xa4code0xa5brief0xadtest content0xa6author0xa3fyz

怎么看起来好像比上面的json还长?其实不是的,要知道0x81什么的才一个字节,所以打印出来就是这样的:

üñblogàñyear═Ñtitleéñlangóenñtext¡SerializationútagñcodeÑbrief¼test contentªauthorúfyz

关于msgpack的协议具体内容,有兴趣的可以自己看看,还是很不错的。不过当初我看msgpack的时候它对unicode的处理有问题,用的时候注意下就行。

conclusion

刚开始是准备长篇大论一番的,不过由于上班也是比较累啊,所以就点到为止了,不过相信看到这里,也明白我的倾向性也是比较明显的,xml我是不推荐的,我一直认为xml是技术的败笔,因为实在太繁琐了,其实要表示信息,大可不必那么做的,可惜它的大腿有点粗,谁让人家有w3c这样的老爹呢,所以就这样吧,现在就能骗骗那些无知小青年;而我对json的态度呢,是比较中立的,它是一个很不错的方法,在可读性和简单上面都不错,所以是一个不错的选择,而且的确现在用的也很广泛;而msgpack我认为在特殊情况下是可以用的,就是当你对传输信息的长度比较在意的时候,例如现在的各种app,用msgpack就比用json节约1/3到1/2的文本流量,这是很可观的,如果你的系统不是太耦合,非得自己实现协议,那么msgpack是一个不错的选择。


img