什么是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)。
这些都是常见的数据结构。事实上大部分现代计算机语言都以某种形式支持它们。这使得一种数据格式在同样基于这些结构的编程语言之间交换成为可能。
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类方法,稍微有点不同,但是改写起来也不是很麻烦。看代码应该就比较清楚了。
##################################################
Python处理json的模块
官方手册:http://docs.python.org/library/json.html
>>>import json >>> json.JSONEncoder().encode({}) '{}' >>> json.JSONEncoder().encode({"name":"daxi"}) '{"name": "daxi"}' >>> json.JSONEncoder().encode({"name":"daxi","age":20}) '{"age": 20, "name": "daxi"}' >>> s = json.JSONEncoder().encode({"name":"daxi","age":20}) >>> s '{"age": 20, "name": "daxi"}' >>> json.JSONDecoder().decode(s) {u'age': 20, u'name': u'daxi'} >>> print json.JSONDecoder().decode(s) {u'age': 20, u'name': u'daxi'} >>> print json.JSONDecoder().decode(s)['age'] 20 >>> print json.JSONDecoder().decode(s)['name'] daxi >>> s = json.JSONEncoder().encode({"name":"daxi","age":20, "city":"北京"}) >>> s '{"city": "\\u5317\\u4eac", "age": 20, "name": "daxi"}' >>> print json.JSONDecoder().decode(s)['city'] 北京
还有一个 http://pypi.python.org/pypi/simplejson/, 暂未测试!
##################################################
json 格式的例子: python 2.5 没有内置的 json 处理模块,可以下载 python-json (json-py) 模块(下载地址: http://pypi.python.org/pypi/python-json)。解压zip包 然后把 json.py 和 minjson.py 考到 /usr/lib/python2.5/下面就行了。
语法:
>>> data = json.read('{"firstname": "Zhongwei", "lastname": "Sun"}') # 前面已经提到了,json 就是一个格式化字符串,所以大括号两侧要加上引号。 写:(感觉这个用处不是很大) >>> test = json.write(data) python 2.6 为例: ## object-->jsonstr Compact encoding: >>> import json
>>> json.dumps([1,2,3,{'4': 5, '6': 7}], separators=(',',':'))
'[1,2,3,{"4":5,"6":7}]'
## jsonstr-->object Decoding JSON: >>> import json
>>> json.loads('["foo", {"bar":["baz", null, 1.0, 2]}]')
###
>>> data=json.loads('{"firstname": "Zhongwei", "lastname": "Sun"}')
>>> print data
{u'lastname': u'Sun', u'firstname': u'Zhongwei'}
>>> {u'lastname': u'Sun', u'firstname': u'Zhongwei'}
{u'lastname': u'Sun', u'firstname': u'Zhongwei'}
>>> print data['firstname']
Zhongwei
>>> import json JSON 的基本介绍: 21世纪初,Douglas Crockford寻找一种简便的数据交换格式,能够在服务器之间交换数据。这其实需要二步,第一步是将各种数据转化为一个字符串,也就是数据的串行化(serialization),第二步才是交换这个字符串。 当时通用的数据交换语言是XML,但是Douglas Crockford觉得XML的生成和解析都太麻烦,所以他提出了一种简化格式,也就是Json。 Json的规格非常简单,只用一个页面、几百个字就能说清楚,而且Douglas Crockford声称这个规格永远不必升级,因为该规定的都规定了。 1) 并列的数据之间用逗号(“,”)分隔。 2) 映射用冒号(“:”)表示。 3) 并列数据的集合(数组)用方括号("[]")表示。 4) 映射的集合(对象)用大括号(“{}”)表示。 上面四条规则,就是Json格式的所有内容。 比如,下面这句话: “北京市的面积为16800平方公里,常住人口1600万人。上海市的面积为6400平方公里,常住人口1800万。” 写成json格式就是这样: [ 如果事先知道数据的结构,上面的写法还可以进一步简化: [ 由此可以看到,json非常易学易用。所以,在短短几年中,它就取代xml,成为了互联网上最受欢迎的数据交换格式。 我猜想,Douglas Crockford一定事先就知道,数据结构可以简化成三种形式,否则怎么可能将json定义得如此精炼呢! ##### 最近发现json解释时,不同人,用同个json库写的代码不一样(所调方法函数不一致,不同用法会出现代码不兼容)。 smiplejson 2.09 下载 http://pypi.python.org/pypi/simplejson/
minjosn : 1.8272049427 本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/toontong/archive/2009/12/10/4979572.aspx 香巴拉工作的一个小例子: def get_sharedInfo(sql): # be shared.. # report_data_s=unicode(report_data_s.encode("utf-8")) |
##################################################
import copy
class Obj(object):
def __init__(self,num):
self.num=num
def __str__(self):
return str(self.num)
__repr__=__str__
def test(fun):
a=[ Obj(10),Obj(11) ]
b=fun(a)
print 'a=%s,b=%s'%(a,b)
a.reverse()
a[0].num=100
print 'a=%s,b=%s'%(a,b)
print '='
test(lambda _:_)
print 'copy.copy'
test(copy.copy)
print 'copy.deepcopy'
test(copy.deepcopy)
In [14]: b=copy.copy(a)
In [15]: b
Out[15]: [[1, 2], (3, 5), 123, [1, 2, 3, 4]]
In [16]: b[2]=456
In [17]: b
Out[17]: [[1, 2], (3, 5), 456, [1, 2, 3, 4]]
In [18]: a
Out[18]: [[1, 2], (3, 5), 123, [1, 2, 3, 4]]
In [19]: b[0][1]=0
In [20]: a
Out[20]: [[1, 0], (3, 5), 123, [1, 2, 3, 4]]
In [21]: b
Out[21]: [[1, 0], (3, 5), 456, [1, 2, 3, 4]]
copy.copy只是复制的a本身,a里面的对象并没有被复制,还是引用的
In [22]: c=copy.deepcopy(a)
In [23]: a
Out[23]: [[1, 0], (3, 5), 123, [1, 2, 3, 4]]
In [24]: c
Out[24]: [[1, 0], (3, 5), 123, [1, 2, 3, 4]]
In [25]: c[0][1]=12
In [26]: c
Out[26]: [[1, 12], (3, 5), 123, [1, 2, 3, 4]]
In [27]: a
Out[27]: [[1, 0], (3, 5), 123, [1, 2, 3, 4]]
copy.deepcopy是连内部的对象一块复制的