0%

python | 模块 json

python 关于解析 json 的模块。

json

Python内置了json包来帮助我们完成对json的操作。

Python的字典结构导出到json使用json.dumps() ,将json读成Python的字典结构,使用json.loads()

如果不是针对string操作而是对文件操作,分别使用json.load()函数和json.dump()函数。

使用 json 进行转换存在一个潜在的问题。

由于 json 语法规定 数组或对象之中的字符串必须使用双引号,不能使用单引号。如果字符串中有单引号,转化为字典,可以用 eval 函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import json

data = {
'name' : 'ACME',
'shares' : 100,
'price' : 542.23
}

json_str = json.dumps(data)
data = json.loads(json_str)

# Writing JSON data to file
with open('data.json', 'w') as f:
json.dump(data, f)

# Reading data back
with open('data.json', 'r') as f:
data = json.load(f)

数据类型对应

json python
object dict
array list
string unicode
number(int) int,long
number(real) float
true True
false False
null None

其他数据类型与Json之间的编码和解码

一般来说,Pythonjson的解析是listdict之间的操作,如果需要其他类型与json之间转换,就需要object_hook参数。先定义一个类,将类的字典初始化成jsonkey-value键值对。这样,json的参数就变成了类的属性。

将一个JSON字典转换为一个Python对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
data = {
'name' : 'ACME',
'shares' : 100,
'price' : 542.23
}

class JSONObject:
def __init__(self, d):
self.__dict__ = d


data = json.loads(data, object_hook=JSONObject)
data.name
'ACME'
data.shares
50
data.price
490.1

还可以通过指定“函数”来进行转换。「这个我没尝试过,只是贴上来了」

用函数来指定序列化的方法,即将对象的“属性-值”对变成字典对,函数返回一个字典,然后json.dumps会格式化这个字典。

如果是通过函数将json变成对象,首先获得类名,然后通过__new__来创建一个对象(不调用初始化函数),然后将json字典的各个属性赋给对象。

使用函数指定json转换方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def serialize_instance(obj):
d = { '__classname__' : type(obj).__name__ }
d.update(vars(obj))
return d

# Dictionary mapping names to known classes
classes = {
'Point' : Point
}

def unserialize_object(d):
clsname = d.pop('__classname__', None)
if clsname:
cls = classes[clsname]
obj = cls.__new__(cls) # Make instance without calling __init__
for key, value in d.items():
setattr(obj, key, value)
return obj
else:
return d

使用方法如下:

1
2
3
4
5
6
7
8
9
10
11
p = Point(2,3)
s = json.dumps(p, default=serialize_instance)
s
'{"__classname__": "Point", "y": 3, "x": 2}'
a = json.loads(s, object_hook=unserialize_object)
a
<__main__.Point object at 0x1017577d0>
a.x
2
a.y
3

eval

通过 eval 进行转换就不存在上面使用 json 进行转换的问题。

1
2
3
4
5
6
7
8
>>> user_info = '{"name" : "john", "gender" : "male", "age": 28}'
>>> user_dict = eval(user_info)
>>> user_dict
{'gender': 'male', 'age': 28, 'name': 'john'}
>>> user_info = "{'name' : 'john', 'gender' : 'male', 'age': 28}"
>>> user_dict = eval(user_info)
>>> user_dict
{'gender': 'male', 'age': 28, 'name': 'john'}

但是,使用 eval 却存在安全性的问题。

1
2
3
4
5
>>> user_info = raw_input(’input user info: ’) 
# 输入 {“name” : “john”, “gender” : “male”, “age”: 28},没问题

>>> user_dict = eval(user_info)
# 输入 import(‘os’).system(‘dir’),user_dict 会列出当前的目录文件!

ast.literal_eval

使用 ast.literal_eval 进行转换既不存在使用 json 进行转换的问题,也不存在使用 eval 进行转换的 安全性问题,因此推荐使用 ast.literal_eval

1
2
3
4
5
6
7
8
9
>>> import ast
>>> user = '{"name" : "john", "gender" : "male", "age": 28}'
>>> user_dict = ast.literal_eval(user)
>>> user_dict
{'gender': 'male', 'age': 28, 'name': 'john'}
user_info = "{'name' : 'john', 'gender' : 'male', 'age': 28}"
>>> user_dict = ast.literal_eval(user)
>>> user_dict
{'gender': 'male', 'age': 28, 'name': 'john'}
请我喝杯咖啡吧~