概念:

JSON(JavaScript Object Notation):是一种轻量级的数据交换格式。 易于人阅读和编写。同时也易于机器解析和生成。 它基于JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。 这些特性使JSON成为理想的数据交换语言。

JSON建构于两种结构:

  • “名称/值”对的集合(A collection of name/value pairs)。不同的语言中,它被理解为对象(object),纪录(record),结构(struct),字典(dictionary),哈希表(hash table),有键列表(keyed list),或者关联数组 (associative array)。
  • 值的有序列表(An ordered list of values)。在大部分语言中,它被理解为数组(array)。

这些都是常见的数据结构。事实上大部分现代计算机语言都以某种形式支持它们。这使得一种数据格式在同样基于这些结构的编程语言之间交换成为可能。

序列化(Serialization):将对象的状态信息转换为可以存储或可以通过网络传输的过程,传输的格式可以是JSON、XML等。反序列化就是从存储区域(JSON,XML)读取反序列化对象的状态,重新创建该对象。

Python2.6开始加入了JSON模块,无需另外下载,Python的Json模块序列化与反序列化的过程分别是 encoding和 decoding

encoding:把一个Python对象编码转换成Json字符串
decoding:把Json格式字符串解码转换成Python对象
对于简单数据类型(string、unicode、int、float、list、tuple、dict),可以直接处理。

json详细讲解参见:http://json.org/json-zh.html

Python操作json的标准api库参考:https://docs.python.org/3/library/json.html

1、简单数据类型的encoding和decoding:

>>> import json
>>> obj = [[1,2,3], 12, 12.3, 'abc', {123:(1,2,3), 'key1':[1,2], 'key2':[3,4]}]
>>> encodedjson = json.dumps(obj)
>>> print(repr(obj))
[[1, 2, 3], 12, 12.3, 'abc', {'key1': [1, 2], 123: (1, 2, 3), 'key2': [3, 4]}]
>>> print(encodedjson)
[[1, 2, 3], 12, 12.3, "abc", {"key1": [1, 2], "123": [1, 2, 3], "key2": [3, 4]}]
>>>

简单类型的数据通过encode之后与原始的repr()输出结果神似;部分数据类型存在差异,例如上例中的元组转换为列表,字典中键为123的整型转化为字符串类型。在json的编码过程中,会存在从python原始类型向json类型的转化过程,具体的转化对照如下:

json.dumps()方法返回了一个str对象encodedjson,json.loads()函数可以将encodedjson进行decode,得到原始数据:

>>> decodedjson = json.loads(encodedjson)
>>> print(type(decodedjson))
<class 'list'>
>>> print(decodedjson)
[[1, 2, 3], 12, 12.3, 'abc', {'key1': [1, 2], '123': [1, 2, 3], 'key2': [3, 4]}]
>>> print(decodedjson[4]['123'])
[1, 2, 3]
>>>

注意上述decodedjson[4]['123']的键仍为字符串,并未转化为原始的数据类型(int),建议在字典key中采用基本的字符串类型。

>>> kk = {1:[1,2,3],False:[3,5],None:2}
>>> kkd = json.dumps(kk)
>>> print(kkd)
{"false": [3, 5], "1": [1, 2, 3], "null": 2}
>>> kkl = json.loads(kkd)
>>> print(kkl)
{'1': [1, 2, 3], 'null': 2, 'false': [3, 5]}
>>>

从json到python的类型转化对照如下:

json.dumps方法提供了很多好用的参数可供选择,比较常用的有sort_keys(对dict对象进行排序,我们知道默认dict是无序存放的),separators,indent等参数。

排序功能使得存储的数据更加有利于观察,也使得对json输出的对象进行比较,例如:

>>> data_1 = {'b':789, 'c':456, 'a':123}
>>> data_2 = {'a':123, 'b':789, 'c':456}
>>> d1 = json.dumps(data_1, sort_keys=True)
>>> d2 = json.dumps(data_2)
>>> d3 = json.dumps(data_2, sort_keys=True)
>>> print(d1)
{"a": 123, "b": 789, "c": 456}
>>> print(d2)
{"c": 456, "b": 789, "a": 123}
>>> print(d3)
{"a": 123, "b": 789, "c": 456}
>>> print(d1 == d2)
False
>>> print(d1 == d3)
True
>>> print(data_1 == data_2)
True
>>>

上例中,本来data1和data2数据应该是一样的,但是由于dict存储的无序特性,造成两者无法比较。因此两者可以通过排序后的结果进行存储就避免了数据比较不一致的情况发生,但是排序后再进行存储,系统必定要多做一些事情,也一定会因此造成一定的性能消耗,所以适当排序是很重要的。

indent参数是缩进的意思,它可以使得数据存储的格式变得更加优雅。

>>> data_1 = {'b':789, 'c':456, 'a':123}
>>> d1 = json.dumps(data_1, sort_keys=True, indent=4)
>>> print(d1)
{
"a": 123,
"b": 789,
"c": 456
}
>>>

输出的数据被格式化之后,可读性更强,但是需要增加一些冗余的空白符进行填充的。json作为一种数据通信的格式,而网络通信是很在乎数据的大小的,无用的空格会占据更多的通信带宽,所以适当时候需要对数据进行压缩。separator参数可以起到这样的作用,该参数传递一个元组,包含分割对象的字符串。

>>> data = {'b':789, 'c':456, 'a':123}
>>> print('DATA:',repr(data))
DATA: {'c': 456, 'a': 123, 'b': 789}
>>> print('repr(data) :', len(repr(data)))
repr(data) : 30
>>> print('dumps(data) :', len(json.dumps(data)))
dumps(data) : 30
>>> print('dumps(data, indent=4) :', len(json.dumps(data, indent = 4)))
dumps(data, indent=4) : 44
>>> print('dumps(data, separators):', len(json.dumps(data, separators=(',', ':'))))
dumps(data, separators : 25
>>>

另一个比较有用的dumps参数是skipkeys,默认为False。 dumps方法存储dict对象时,key必须是str类型,如果出现了其他类型的话,那么会产生TypeError异常,如果开启该参数,设为True的话,则会比较优雅的过度。

>>> data = {'b':789,'c':456,(1,2):123, 456:678}
>>> print(json.dumps(data))
Traceback (most recent call last):
File "<pyshell#12>", line 1, in <module>
print(json.dumps(data))
File "D:\Python\lib\json\__init__.py", line 230, in dumps
return _default_encoder.encode(obj)
File "D:\Python\lib\json\encoder.py", line 192, in encode
chunks = self.iterencode(o, _one_shot=True)
File "D:\Python\lib\json\encoder.py", line 250, in iterencode
return _iterencode(o, 0)
TypeError: keys must be a string
>>> print(json.dumps(data, skipkeys=True))
{"456": 678, "b": 789, "c": 456}
>>>

2、处理自定义的数据类型:

json模块不仅可以处理普通的python内置类型,也可以处理我们自定义的数据类型,而往往处理自定义的对象是很常用的。

首先,我们在Person模块中定义一个类Person。

#!/usr/local/bin/python3
# -*- coding:utf-8 -*-
# autor:antclonies import json class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
def __repr__(self):
return 'Person Object name : %s, age : %d'%(self.name, self.age) if __name__ == '__main__':
p = Person('Peter', 22)
print(p)
dmp = json.dumps(p)
print(dmp)

运行以上模块:

[root@ant-colonies tmp]# ./py_2.py
Person Object name : Peter, age : 22
Traceback (most recent call last):
...
File "/usr/local/lib/python3.5/json/encoder.py", line 179, in default
raise TypeError(repr(o) + " is not JSON serializable")
TypeError: Person Object name : Peter, age : 22 is not JSON serializable

如果直接通过json.dumps方法对Person的实例进行处理的话,会报错,因为json不知道怎样转化这个Person类型的实例p。通过上面所提到的json和python的类型转化对照表,可以发现,object类型和dict相关联,所以我们需要把我们自定义的类型转化为dict,然后再进行处理。这里,有两种方法可以使用。

方法一:自己写转化函数

#!/usr/local/bin/python3
# -*- coding:utf-8 -*-
# import json
import Person p = Person.Person('Peter', 22) def obj2dict(obj):
'''convert object to dict'''
d = {}
d['__class__'] = obj.__class__.__name__
d['__module__'] = obj.__module__
d.update(obj.__dict__)
return d def dict2obj(dmp):
'''convert dict to object'''
if '__class__' in d:
class_name = d.pop('__class__')
module_name = d.pop('__module__')
module = __import__(module_name)
class_ = getattr(module, class_name)
args = dict((key, value) for key, value in d.items()) # get args
inst = class_(**args) # create new instance
else:
inst = d
return inst d = obj2dict(p)
print(d)
'''{'__module__': 'Person', '__class__': 'Person', 'name': 'Peter', 'age': 22}''' o = dict2obj(d)
print(type(o), o)
'''<class 'Person.Person'> Person Object name : Peter, age : 22''' dump = json.dumps(p, default=obj2dict)
print(dump)
'''{"__module__": "Person", "__class__": "Person", "name": "Peter", "age": 22}''' load = json.loads(dump, object_hook=dict2obj)
print(load)
'''{'name': 'Peter', 'age': 22}'''

上面代码已经写的很清楚了,实质就是自定义object类型和dict类型进行转化。object2dict函数将对象模块名、类名以及__dict__存储在dict对象里,并返回。dict2object函数则是反解出模块名、类名、参数,创建新的对象并返回。在json.dumps 方法中增加default参数,该参数表示在转化过程中调用指定的函数,同样在decode过程中json.loads方法增加object_hook,指定转化函数。

方法二:继承JSONEncoder和JSONDecoder类,覆写相关方法

JSONEncoder类负责编码,主要是通过其default函数进行转化,我们可以override该方法。同理对于JSONDecoder。

#!/usr/local/bin/python3
# -*- coding:utf-8 -*-
# import json
import Person p = Person.Person('Peter', 22) class MyEncoder(json.JSONEncoder):
def default(self, obj):
'''convert object to dict'''
d = {}
d['__class__'] = obj.__class__.__name__
d['__module__'] = obj.__module__
d.update(obj.__dict__)
return d class MyDecoder(json.JSONDecoder):
def __init__(self):
json.JSONDecoder.__init__(self, object_hook=self.dict2obj)
def dict2obj(self, d):
'''convert dict to object'''
if '__class__' in d:
class_name = d.pop('__class__')
module_name = d.pop('__module__')
module = __import__(module_name)
class_ = getattr(module, class_name)
args = dict((key, value) for key, value in d.items()) # get args
inst = class_(**args) # create new instance
else:
inst = d
return inst d = MyEncoder().encode(p)
o = MyDecoder().decode(d) print(d)
print(type(o), o) '''
{"name": "Peter", "age": 22, "__module__": "Person", "__class__": "Person"}
<class 'Person.Person'> Person Object name : Peter, age : 22
'''

参考了:

http://www.cnblogs.com/coser/archive/2011/12/14/2287739.html
https://docs.python.org/3/library/json.html
http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00143192607210600a668b5112e4a979dd20e4661cc9c97000

Python 中数据的序列化和反序列化(json处理)的更多相关文章

  1. python中class的序列化和反序列化

    对于类的序列化:将类的成员变量名和数据作为一对键值对存储在物理内存中,例如 class A(object): def __init__(self): self.a = o self.b = 1 sel ...

  2. day5-python中的序列化与反序列化-json&pickle

    一.概述 玩过稍微大型一点的游戏的朋友都知道,很多游戏的存档功能使得我们可以方便地迅速进入上一次退出的状态(包括装备.等级.经验值等在内的一切运行时数据),那么在程序开发中也存在这样的需求:比较简单的 ...

  3. Jackson序列化和反序列化Json数据完整示例

    Jackson序列化和反序列化Json数据 Web技术发展的今天,Json和XML已经成为了web数据的事实标准,然而这种格式化的数据手工解析又非常麻烦,软件工程界永远不缺少工具,每当有需求的时候就会 ...

  4. 对 JSON 数据进行序列化和反序列化

    如何:对 JSON 数据进行序列化和反序列化 2017/03/30 作者 JSON(JavaScript 对象符号)是一种高效的数据编码格式,可用于在客户端浏览器和支持 AJAX 的 Web 服务之间 ...

  5. Json数据的序列化与反序列化的三种经常用法介绍

    下面内容是本作者从官网中看对应的教程后所做的demo.其体现了作者对相关知识点的个人理解..作者才疏学浅,难免会有理解不到位的地方.. 还请各位读者批判性对待... 本文主要介绍在Json数据的序列化 ...

  6. python之数据的序列化

    参考博客:http://www.cnblogs.com/yyds/p/6563608.html 数据的序列化功能表 json.dumps() 将python数据类型转换为(json)字符串 json. ...

  7. Python 入门之 内置模块 -- 序列化模块(json模块、pickle模块)

    Python 入门之 内置模块 -- 序列化模块(json模块.pickle模块) 1.序列化 Python中这种序列化模块有三种: ​ json模块 : ​ 不同语言都遵循的一种数据转化格式,即不同 ...

  8. C#序列化及反序列化Json对象通用类JsonHelper

    当今的程序界Json大行其道.因为Json对象具有简短高效等优势,广受广大C#码农喜爱.这里发一个序列化及反序列化Json对象通用类库,希望对大家有用. public class JsonHelper ...

  9. (推荐JsonConvert )序列化和反序列化Json

    在Json文本和.Net对象之间转换最快的方法是试用JsonSerializer. JsonSerializer通过将.Net对象属性名称映射到Json属性名称,并为其复制值,将.Net对象转换为其J ...

随机推荐

  1. vmware10中arch使用遇到的一些问题

    xfce4中安装中文输入法fcitx step 1  #pacman -S fcitx-im setp 2 在~/.xinitrc中添加如下内容: export LC_ALL=zh_CN.UTF-8e ...

  2. POJ - 2109 Power of Cryptography(高精度log+二分)

    Current work in cryptography involves (among other things) large prime numbers and computing powers ...

  3. EasyUI控件combobox重复请求后台,dialog窗口数据异常

    最近在用Easy UI+Dapper+MVC4 开发一个财务收款系统,其中就发现一些小问题,供有需要的人参考. 1.EasyUI控件combobox 数据绑定 出现重复请求后台 上代码: <td ...

  4. Java 文件上传至leanCloud

    首先,在Controller端入参设置为 @RequestParam(value = "file",defaultValue = "") MultipartFi ...

  5. 学习使用MS SQL Server游标(CURSOR)

    说实的,使用MS SQL Server这样久,游标一直没有使用过.以前实现相似的功能,都是使用WHILE循环加临时表来实现.刚才有参考网上示例练习写了一下.了解到游标概念与语法. 下面代码示例中,先是 ...

  6. Glib学习笔记(四)

    你将学到什么 使用GObject模拟实现接口 使用接口 首先按照学习笔记(一)定义一个普通的GObject类 使用G_DEFINE_TYPE_WITH_CODE和G_IMPLEMENT_INTERFA ...

  7. Redis在window下安装以及配置

    一.安装Redis 1.Redis官网下载地址:http://redis.io/download,下载相应版本的Redis,在运行中输入cmd,然后把目录指向解压的Redis目录. 2.启动服务命令 ...

  8. 【转】C#日期时间格式化

    源地址:https://www.cnblogs.com/polk6/p/5465088.html

  9. IO相关2(文件输入输出)

    除了继承自 iostream 类型的行为之外,fstream 中定义的类型还增加了一些新的成员来管理与流相关的文件.我们可以对 fstream,ifstream 和 ofstream 对象调用这些操作 ...

  10. pip_install的安装

    1.下载get-pip.py https://pip.pypa.io/en/latest/installing/#id9 2.运行 python get-pip.py 3.python -m pip ...