python对json的相关操作实例详解


Posted in Python onJanuary 04, 2017

本文实例分析了python对json的相关操作。分享给大家供大家参考,具体如下:

什么是json:

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)。

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

json官方说明参见:http://json.org/

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

对简单数据类型的encoding 和 decoding:

使用简单的json.dumps方法对简单数据类型进行编码,例如:

import json
obj = [[1,2,3],123,123.123,'abc',{'key1':(1,2,3),'key2':(4,5,6)}]
encodedjson = json.dumps(obj)
print repr(obj)
print encodedjson

输出:

[[1, 2, 3], 123, 123.123, 'abc', {'key2': (4, 5, 6), 'key1': (1, 2, 3)}]
[[1, 2, 3], 123, 123.123, "abc", {"key2": [4, 5, 6], "key1": [1, 2, 3]}]

通过输出的结果可以看出,简单类型通过encode之后跟其原始的repr()输出结果非常相似,但是有些数据类型进行了改变,例如上例中的元组则转换为了列表。在json的编码过程中,会存在从python原始类型向json类型的转化过程,具体的转化对照如下:

python对json的相关操作实例详解

json.dumps()方法返回了一个str对象encodedjson,我们接下来在对encodedjson进行decode,得到原始数据,需要使用的json.loads()函数:

decodejson = json.loads(encodedjson)
print type(decodejson)
print decodejson[4]['key1']
print decodejson

输出:

<type 'list'>
[1, 2, 3]
[[1, 2, 3], 123, 123.123, u'abc', {u'key2': [4, 5, 6], u'key1': [1, 2, 3]}]

loads方法返回了原始的对象,但是仍然发生了一些数据类型的转化。比如,上例中‘abc'转化为了unicode类型。从json到python的类型转化对照如下:

python对json的相关操作实例详解

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

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

data1 = {'b':789,'c':456,'a':123}
data2 = {'a':123,'b':789,'c':456}
d1 = json.dumps(data1,sort_keys=True)
d2 = json.dumps(data2)
d3 = json.dumps(data2,sort_keys=True)
print d1
print d2
print d3
print d1==d2
print d1==d3

输出:

{"a": 123, "b": 789, "c": 456}
{"a": 123, "c": 456, "b": 789}
{"a": 123, "b": 789, "c": 456}
False
True

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

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

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

输出:

{
 "a": 123,
 "b": 789,
 "c": 456
}

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

print 'DATA:', repr(data)
print 'repr(data)  :', len(repr(data))
print 'dumps(data)  :', len(json.dumps(data))
print 'dumps(data, indent=2) :', len(json.dumps(data, indent=4))
print 'dumps(data, separators):', len(json.dumps(data, separators=(',',':')))

输出:

DATA: {'a': 123, 'c': 456, 'b': 789}
repr(data)  : 30
dumps(data)  : 30
dumps(data, indent=2) : 46
dumps(data, separators): 25

通过移除多余的空白符,达到了压缩数据的目的,而且效果还是比较明显的。

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

data = {'b':789,'c':456,(1,2):123}
print json.dumps(data,skipkeys=True)

输出:

{"c": 456, "b": 789}

处理自己的数据类型

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

首先,我们定义一个类Person。

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

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

方法一:自己写转化函数

'''
Created on 2011-12-14
@author: Peter
'''
import Person
import json
p = Person.Person('Peter',22)
def object2dict(obj):
 #convert object to a dict
 d = {}
 d['__class__'] = obj.__class__.__name__
 d['__module__'] = obj.__module__
 d.update(obj.__dict__)
 return d
def dict2object(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.encode('ascii'), value) for key, value in d.items()) #get args
 inst = class_(**args) #create new instance
 else:
 inst = d
 return inst
d = object2dict(p)
print d
#{'age': 22, '__module__': 'Person', '__class__': 'Person', 'name': 'Peter'}
o = dict2object(d)
print type(o),o
#<class 'Person.Person'> Person Object name : Peter , age : 22
dump = json.dumps(p,default=object2dict)
print dump
#{"age": 22, "__module__": "Person", "__class__": "Person", "name": "Peter"}
load = json.loads(dump,object_hook = dict2object)
print load
#Person Object name : Peter , age : 22

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

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

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

'''
Created on 2011-12-14
@author: Peter
'''
import Person
import json
p = Person.Person('Peter',22)
class MyEncoder(json.JSONEncoder):
 def default(self,obj):
 #convert object to a 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.dict2object)
 def dict2object(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.encode('ascii'), 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

对于JSONDecoder类方法,稍微有点不同,但是改写起来也不是很麻烦。看代码应该就比较清楚了。

 

Python 相关文章推荐
Python脚本实现DNSPod DNS动态解析域名
Feb 14 Python
Python中的fileinput模块的简单实用示例
Jul 09 Python
python去除字符串中的换行符
Oct 11 Python
Python内置模块turtle绘图详解
Dec 09 Python
浅谈Python中的zip()与*zip()函数详解
Feb 24 Python
Python实现统计英文文章词频的方法分析
Jan 28 Python
Python3.5 Pandas模块之Series用法实例分析
Apr 23 Python
python剪切视频与合并视频的实现
Mar 03 Python
基于python实现matlab filter函数过程详解
Jun 08 Python
利用python对mysql表做全局模糊搜索并分页实例
Jul 12 Python
Python使用paramiko连接远程服务器执行Shell命令的实现
Mar 04 Python
python 利用PyAutoGUI快速构建自动化操作脚本
May 31 Python
python的random模块及加权随机算法的python实现方法
Jan 04 #Python
python 实现红包随机生成算法的简单实例
Jan 04 #Python
Python 模板引擎的注入问题分析
Jan 01 #Python
python getopt详解及简单实例
Dec 30 #Python
浅谈编码,解码,乱码的问题
Dec 30 #Python
Python实现将数据库一键导出为Excel表格的实例
Dec 30 #Python
python脚本实现数据导出excel格式的简单方法(推荐)
Dec 30 #Python
You might like
php生成扇形比例图实例
2013/11/06 PHP
javascript multibox 全选
2009/03/22 Javascript
jquery移动listbox的值原理及代码
2013/05/03 Javascript
JavaScript解析URL参数示例代码
2013/08/12 Javascript
根据身份证号自动输出相关信息(籍贯,出身日期,性别)
2013/11/15 Javascript
引用 js在IE与FF之间的区别详细解析
2013/11/20 Javascript
Javascript中3个需要注意的运算符
2015/04/02 Javascript
理解javascript正则表达式
2016/03/08 Javascript
ionic实现滑动的三种方式
2016/08/27 Javascript
非常优秀的JS图片轮播插件Swiper的用法
2017/01/03 Javascript
jQuery菜单实例(全选,反选,取消)
2017/08/28 jQuery
基于JavaScript实现一个简单的Vue
2018/09/26 Javascript
JavaScript栈和队列相关操作与实现方法详解
2018/12/07 Javascript
jQuery实现简单弹幕效果
2019/11/28 jQuery
js抽奖转盘实现方法分析
2020/05/16 Javascript
微信小程序国际化探索实现(附源码地址)
2020/05/20 Javascript
微信小程序向Java后台传输参数的方法实现
2020/12/10 Javascript
[57:36]DOTA2-DPC中国联赛 正赛 SAG vs CDEC BO3 第三场 2月1日
2021/03/11 DOTA
Python urllib、urllib2、httplib抓取网页代码实例
2015/05/09 Python
Python基于pygame模块播放MP3的方法示例
2017/09/30 Python
Python实现的摇骰子猜大小功能小游戏示例
2017/12/18 Python
influx+grafana自定义python采集数据和一些坑的总结
2018/09/17 Python
Python提取支付宝和微信支付二维码的示例代码
2019/02/15 Python
浅谈pycharm导入pandas包遇到的问题及解决
2020/06/01 Python
构造器Constructor是否可被override?
2013/08/06 面试题
商务日语专业毕业生求职信
2013/10/26 职场文书
财务工作个人求职的自我评价
2013/12/19 职场文书
大课间活动制度
2014/01/18 职场文书
警察群众路线对照检查材料思想汇报
2014/10/01 职场文书
中秋节祝酒词
2015/08/12 职场文书
交通安全教育心得体会
2016/01/15 职场文书
2019银行竞聘书
2019/06/21 职场文书
确保减税降费落地生根,用实实在在措施
2019/07/19 职场文书
一文带你探究MySQL中的NULL
2021/11/11 MySQL
WCG2010 星际争霸决赛 Flash vs Goojila 1 星际经典比赛回顾
2022/04/01 星际争霸
MySql按时,天,周,月进行数据统计
2022/08/14 MySQL