摘要:对于python来说,json并不是一种数据类型,可以把它视为函数。json.dumps把字典或列表变成json风格的str类型;json.loads把json风格的str类型变成原来的类型(列表或者字典)

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

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

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

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

1
2
3
4
5
6
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类型的转化过程,具体的转化对照如下:

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

1
2
3
4
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的类型转化对照如下:

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

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

1
2
3
4
5
6
7
8
9
10
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参数是缩进的意思,它可以使得数据存储的格式变得更加优雅。

1
2
3
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参数可以起到这样的作用,该参数传递是一个元组,包含分割对象的字符串。

1
2
3
4
5
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的话,则会比较优雅的过度。

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

输出:

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

处理自己的数据类型

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

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

1
2
3
4
5
6
7
8
9
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,然后再进行处理。这里,有两种方法可以使用。

方法一:自己写转化函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
'''
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。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
'''
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类方法,稍微有点不同,但是改写起来也不是很麻烦。看代码应该就比较清楚了。

转自:http://www.cnblogs.com/coser/archive/2011/12/14/2287739.html

json python api的更多相关文章

  1. Python第十四天 序列化 pickle模块 cPickle模块 JSON模块 API的两种格式

    Python第十四天 序列化  pickle模块  cPickle模块  JSON模块  API的两种格式 目录 Pycharm使用技巧(转载) Python第一天  安装  shell  文件 Py ...

  2. BotVS开发基础—Python API

    代码 import json def main(): # python API列表 https://www.botvs.com/bbs-topic/443 #状态信息 LogStatus(" ...

  3. 《Spark Python API 官方文档中文版》 之 pyspark.sql (一)

    摘要:在Spark开发中,由于需要用Python实现,发现API与Scala的略有不同,而Python API的中文资料相对很少.每次去查英文版API的说明相对比较慢,还是中文版比较容易get到所需, ...

  4. 《Spark Python API 官方文档中文版》 之 pyspark.sql (二)

    摘要:在Spark开发中,由于需要用Python实现,发现API与Scala的略有不同,而Python API的中文资料相对很少.每次去查英文版API的说明相对比较慢,还是中文版比较容易get到所需, ...

  5. 【Ansible】的python api

    [Ansible API] Ansible本身就是由python写成,所有其对python形式的API的支持应该不错. 其API分不同的版本,这个版本也就是ansible本身的版本,可以通过ansib ...

  6. 《Spark Python API 官方文档中文版》 之 pyspark.sql (四)

    摘要:在Spark开发中,由于需要用Python实现,发现API与Scala的略有不同,而Python API的中文资料相对很少.每次去查英文版API的说明相对比较慢,还是中文版比较容易get到所需, ...

  7. 《Spark Python API 官方文档中文版》 之 pyspark.sql (三)

    摘要:在Spark开发中,由于需要用Python实现,发现API与Scala的略有不同,而Python API的中文资料相对很少.每次去查英文版API的说明相对比较慢,还是中文版比较容易get到所需, ...

  8. 如何在 Apache Flink 中使用 Python API?

    本文根据 Apache Flink 系列直播课程整理而成,由 Apache Flink PMC,阿里巴巴高级技术专家 孙金城 分享.重点为大家介绍 Flink Python API 的现状及未来规划, ...

  9. Appium python API 总结

    Appium python api 根据testerhome的文章,再补充一些文章里面没有提及的API [TOC] [1]find element driver 的方法 注意:这几个方法只能通过sel ...

随机推荐

  1. PMIC RTC 寄存器

    RTC_PDN1 bit 0 - 3 : Android bits bit 4 - 5 : Recovery bits (0x10: factory data reset) bit 6 : Bypas ...

  2. Air Raid(最小路径覆盖)

    Description Consider a town where all the streets are one-way and each street leads from one interse ...

  3. jquery加载页面的方法(页面加载完成就执行)

    jquery加载页面的方法(页面加载完成就执行),建议大家看下windows.onload与$(document).ready之间的区别. 1.$(function(){  $("#a&qu ...

  4. js设计模式(4)---组合模式

    0.前言 今天是建党节,新疆那边又开始了闹腾.作为立志成为码农的我,现在已经从一个大愤青淡化为一个小愤青,对这些国家民生大事不在血气喷发,转而把经历发泄在技术问题上面,因而在扯一篇随笔吧,把无处发泄的 ...

  5. 才趟过的一个坑,css造成的Validform表单提交按钮点击无效

    最近入手的一个项目,在开发的过程中,遇到了一个以前没遇到过的问题,废了半天的功夫才弄懂原因,留下足迹,警醒后人,下面开始讲故事啦! 在一个昏天暗地的上午,我一个人照常坐在办公室安静的工作中!项目编码已 ...

  6. react 入坑笔记(四) - React 事件绑定和传参

    React 事件处理 建议:在了解 js 的 this 取值后食用更佳. 一.react 与 Html 中用法的异同和注意点 html 中的绑定事件的写法: <button onclick=&q ...

  7. Maven(个人整理)(一,未完待续)

                                                      Maven 1. 什么是Maven? 乍一看,Maven看起来很多东西,但简而言之,Maven试图将 ...

  8. 移动端html页面分享

    开发APP应用比开发移动端网页挑战小,因为APP应用只需要适配不同手机即可,而移动端网页不仅需要适配不同手机,还要适配同一部手机的不同浏览器. 移动端页面分享是一个常用的功能,需要宿主环境,可以是某A ...

  9. pandas:根据行间差值进行数据合并

    1. 问题描述 在处理用户上网数据时,用户的上网行为数据之间存在时间间隔,按照实际情况,若时间间隔小于阈值(next_access_time_app),则可把这几条上网行为合并为一条行为数据:若时间间 ...

  10. Request常用方法(转)

    原文地址:http://www.lihuai.net/program/python/1617.html Python Requests库:HTTP for Humans 时间: 2014/12/30 ...