为什么需要 JSON
大家都在 淘宝、京东、拼多多 上购物过。
线上购物可能使用的是手机, 也有在电脑浏览器上。
这些手机上的 淘宝、京东 应用 和 电脑浏览器里面运行的网站页面 我们统称 客户端
。
客户端为什么能呈现出琳琅满目的商品? 这些商品信息都是从淘宝和京东的 网站服务器
获取的
客户端
和 服务器
之间 需要交换 数据 才能完成各种功能。
比如:获取 最近的交易列表, 提交新的订单。
这些数据 在 客户端 或者服务器 产生的时候, 是客户端程序 和服务端程序 的内部 数据对象。
假设 服务端程序都是用Python语言开发的话, 那么, 服务端从数据库中获取的最近的交易列表,可能就是像下面这样的一个python 列表对象:
historyTransactions = [
{
'time' : '20170101070311', # 交易时间
'amount' : '3088', # 交易金额
'productid' : '45454455555', # 货号
'productname' : 'iphone7' # 货名
},
{
'time' : '20170101050311', # 交易时间
'amount' : '18', # 交易金额
'productid' : '453455772955', # 货号
'productname' : '奥妙洗衣液' # 货名
},
...
]
现在的问题是,我们怎么把这样的一个 存在于内存中的数据对象传递给 客户端呢?
客户端收到 数据后,又要怎样转变为 它的程序语言中 的数据对象呢? 因为变成 程序语言中的对象,这样才方便处理。
这个过程,就好像 两个人聊天时,双方 需要把自己脑子中的 事物 转化为 语言描述传递给对方, 接收到对方的语言描述,再转化为自己的脑子中的事物一样。
通常,我们把程序的各种类型数据对象 变成 表示该数据对象的 字节串 这个过程 称之为 序列化 。
而把 字节串转化为 程序中的数据对象 这个过程 称之为 反序列化
我们通过任何传输协议 (当前 用的比较多的是 http协议) 传送信息,传输的都是 好的字节串
。
而且 不同的客户端、服务端程序可能使用不同的语言。为了方便 不同的编程语言 处理, 这个序列化后的 格式 应该是各种语言都 方便 处理的。
使用什么样的序列化 格式 这是 一个 重要问题。
以前的流行的解决方案是 XML。 需要我们自己开发代码 把 像 上面的数据对象 序列化 为XML 文档, 传输出去。
比如
<transactinlist>
<trans>
<time>20170101070311</time>
<amount>3088</amount>
<productid>45454455555</productid>
<productname>iphone7</productname>
</trans>
<trans>
<time>20170101050311</time>
<amount>18</amount>
<productid>453455772955</productid>
<productname>奥妙洗衣液</productname>
</trans>
</transactinlist>
接收方收到后,再反序列化 为 它的程序里面的 数据对象,进行处理。
XML的一个弊端就是 序列化性能相对比较低, 而且转化后的数据体积增大很多。
最近的主流方案 就是使用 : JSON 格式
JSON (JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式。
它是 javascript 规范里面定义的。 它是一种文本格式来存储和表示数据。
它的特点就是 简洁 并且 清晰, 人都能很容易的看明白。
也方便 程序 解析和生成,相比XML,序列化和反序列化的效率都高很多,而且产生的数据量也小很多。
任何编程语言都可以使用这种格式。 而且很多编程语言的解释器内置了库,可以很方便的序列化和反序列化。 包括 Python、 Javascript 等。
序列化和反序列化
Python中内置了json这个库,可以 方便的把内置的数据对象 序列化为json格式文本的字符串。
比如,我们要把上面的数据对象序列化为json格式的字符串,就可以使用该库里面的dumps函数,像这样
import json
historyTransactions = [
{
'time' : '20170101070311', # 交易时间
'amount' : '3088', # 交易金额
'productid' : '45454455555', # 货号
'productname' : 'iphone7' # 货名
},
{
'time' : '20170101050311', # 交易时间
'amount' : '18', # 交易金额
'productid' : '453455772955', # 货号
'productname' : '奥妙洗衣液' # 货名
}
]
# dumps 方法将数据对象序列化为 json格式的字符串
jsonstr = json.dumps(historyTransactions)
print(jsonstr)
打印出来的结果是这样的
[{"time": "20170101070311", "amount": "3088", "productid": "45454455555", "productname": "iphone7"}, {"time": "20170101050311", "amount": "18", "productid": "453455772955", "productname": "\u5965\u5999\u6d17\u8863\u6db2"}]
大家可以发现,json格式表示数据 和我们Python语言本身表示数据非常的像。
当然有些不同,比如字符串只能用双引号,列表最后一个元素后面不能有逗号等。
序列化后的结果,也是一个!!!字符串。 json格式本身就是一个字符串。
然后我们可以存储到文件,或者从网络发送出去。
这样就完成了数据对象的发送。
可能有的朋友发现了中文部分的数据
奥妙洗衣液
经过json转化后变成了
\u5965\u5999\u6d17\u8863\u6db2
这是因为,json.dumps 方法发现将字符串中如果有非ascii码字符,比如中文, 缺省就用该字符的unicode数字来表示。
比如 奥
的unicode是 5965, 就表示为 \u5965
如果你不想这样,可以给参数 ensure_ascii 赋值为 False,如下所示
json.dumps(historyTransactions,ensure_ascii=False,indent=4)
其中,indent参数表示转换后缩进为4,这样显得整洁好看,
这样,转换后,运行结果如下
[
{
"time": "20170101070311",
"amount": "3088",
"productid": "45454455555",
"productname": "iphone7"
},
{
"time": "20170101050311",
"amount": "18",
"productid": "453455772955",
"productname": "奥妙洗衣液"
}
]
接收方如果也是Python开发的,可以使用 json库中的 loads方法,把json格式的字符串变为 Python中的数据对象
比如
import json
jsonstr = '[{"time": "20170101070311", "amount": "3088", "productid": "45454455555", "productname": "iphone7"}, {"time": "20170101050311", "amount": "18", "productid": "453455772955", "productname": "\u5965\u5999\u6d17\u8863\u6db2"}]'
translist = json.loads(jsonstr)
print(translist)
print(type(translist))
输出结果如下
[{'time': '20170101070311', 'amount': '3088', 'productid': '45454455555', 'productname': 'iphone7'}, {'time': '20170101050311', 'amount': '18', 'productid': '453455772955', 'productname': '奥妙洗 衣液'}]
<class 'list'>
可以发现,确实转变成为了list对象。
这样接收方程序就可以方便的处理里面的数据了。