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是编译运行的验证方法
Jan 30 Python
python实现逆波兰计算表达式实例详解
May 06 Python
Python如何抓取天猫商品详细信息及交易记录
Feb 23 Python
详解windows python3.7安装numpy问题的解决方法
Aug 13 Python
Python发送邮件功能示例【使用QQ邮箱】
Dec 04 Python
Python3.7基于hashlib和Crypto实现加签验签功能(实例代码)
Dec 04 Python
python中的逆序遍历实例
Dec 25 Python
python pip安装包出现:Failed building wheel for xxx错误的解决
Dec 25 Python
树莓派4B安装Tensorflow的方法步骤
Jul 16 Python
Python 使用生成器代替线程的方法
Aug 04 Python
使用Python解析Chrome浏览器书签的示例
Nov 13 Python
flask框架中的cookie和session使用
Jan 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导出MySQL数据到Excel文件(fputcsv)
2011/07/03 PHP
PHP删除数组中的特定元素的代码
2012/06/28 PHP
详解PHP对象的串行化与反串行化
2016/01/24 PHP
Js如何判断客户端是PC还是手持设备简单分析
2012/11/22 Javascript
js获得网页背景色和字体色的方法
2014/03/21 Javascript
通过JQuery将DIV的滚动条滚动到指定的位置方便自动定位
2014/05/05 Javascript
jQuery中noConflict()用法实例分析
2015/02/08 Javascript
快速学习jQuery插件 jquery.validate.js表单验证插件使用方法
2015/12/01 Javascript
移动端点击态处理的三种实现方式
2017/01/12 Javascript
VUE实现日历组件功能
2017/03/13 Javascript
JS正则获取HTML元素的方法
2017/03/31 Javascript
React Native中的RefreshContorl下拉刷新使用
2017/10/09 Javascript
Vue CLI 3搭建vue+vuex最全分析(推荐)
2018/09/27 Javascript
js实现圆形显示鼠标单击位置
2020/02/11 Javascript
Node.js API详解之 V8模块用法实例分析
2020/06/05 Javascript
用Python程序抓取网页的HTML信息的一个小实例
2015/05/02 Python
在Python中操作字典之clear()方法的使用
2015/05/21 Python
基于MTCNN/TensorFlow实现人脸检测
2018/05/24 Python
Django实现表单验证
2018/09/08 Python
python实现在图片上画特定大小角度矩形框
2018/10/24 Python
Python下划线5种含义代码实例解析
2020/07/10 Python
Python3爬虫中关于中文分词的详解
2020/07/29 Python
详解css position 5种不同的值的用法
2019/07/30 HTML / CSS
原生canvas制作画图小工具的踩坑和爬坑
2020/06/09 HTML / CSS
美国体育用品商店:Paragon Sports
2017/10/08 全球购物
临床医学大学生求职信
2013/09/28 职场文书
中专生学习生活的自我评价分享
2013/10/27 职场文书
医院实习介绍信
2014/01/12 职场文书
运动会入场词100字
2014/02/06 职场文书
小学语文教学反思
2014/02/10 职场文书
新法人代表任命书
2014/06/06 职场文书
解除劳动合同证明书
2014/09/26 职场文书
学校政风行风自查自纠报告
2014/10/21 职场文书
中学音乐课教学反思
2016/02/18 职场文书
奖学金申请书(范文)
2019/08/14 职场文书
给numpy.array增加维度的超简单方法
2021/06/02 Python