Python的内置库——json处理

{"firstName":"John", "lastName":"Doe"}

对于dictionaries,keys需要是字符串类型(字典中任何非字符串类型的key在编码时会先转换为字符串)。而且,在web应用程序中,顶层对象被编码为一个字典是一个标准做法。

这句话大概意思是:

  1. {} 开头和结尾
  2. str表示 key
  3. str, int, list, dict 表示 value
  4. list用[index]访问
  5. dict用.key访问

json 字符串生成 python 对象:json.load()
python 对象格式化为 json 字符串:json.dump()

数据类型

转换对应表(python -> json)

PythonJSON
dictobject
list, tuplearray
strstring
int, floatnumber
Truetrue
Falsefalse
Nonenull

转换对应表(json -> python)

JSONPython
objectdict
arraylist
stringstr
number(int)int
number(real)float
trueTrue
falseFalse
nullNone

常用方法

方法功能总结
json.dump(obj,fp)将python数据类型转换并保存到json格式文件内p -> j,写入文件
json.dumps(obj)将python数据类型转换为json格式的字符串p -> j
json.load(fp)从json格式的文件中读取数据并转换为python的类型从文件读, j -> p
json.loads(str)将json格式的字符串转换为python的类型j -> p

带s的是处理字符串
不带s的是从文件里处理

json

Python -> JSON

json.dump(obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)

json.dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)

  • obj:需要被转换的Python对象
  • fp:文件对象,要写入的文件
  • skipkeys
    • Fasle时:不是基本对象(int、str、bool、float)的键不会被跳过
    • True时:不是基本对象(int、str、bool、float)的键会被跳过
  • ensure_ascii
    • True:将非ASCII字符转义,例如中文
    • False:将非ASCII字符原样输出
  • allow_nan
    • True:对json规格范围外的float类型(nan、inf、-inf)序列化时会引发ValueError
    • False:对json规格范围外的float类型(nan、inf、-inf)序列化时使用等价形式(NaN、Infinity、-Infinity)
  • indent:指定缩进等级(非负整数/字符串)
    • 0、负数、””:只添加换行符
    • None:不缩进
    • 正整数:每层缩进同样数量的空格
    • 字符串:如\t,该字符串将被用于缩进每一层
  • sort_keys:按字典的键排序
  • default:其应该是一个函数,每当某个对象无法被序列化时它会被调用。它应该返回该对象的一个可以被 JSON 编码的版本或者引发一个 TypeError
  1. 使用dumps()
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
import json

# 这是一个 python 字典对象
py_dic = {
'firstName': 'Boii',
'j': {
'x': 1,
'y': "2",
'z': 3
},
"lastName": "Pro",
'li': ["A", 'b', 3]
}

print('Python对象:', end="")
print(py_dic, end="\t")
print(type(py_dic))

# 将一个 Python 对象转换成 json 字符串
json_str = json.dumps(py_dic, sort_keys=True)

print('JSON字符串:', end="")
print(json_str, end="\t")
print(type(json_str))

--------------------------------------------------

# Output:
Python对象:{'firstName': 'Boii', 'j': {'x': 1, 'y': '2', 'z': 3}, 'lastName': 'Pro', 'li': ['A', 'b', 3]} <class 'dict'>
JSON字符串:{"firstName": "Boii", "j": {"x": 1, "y": "2", "z": 3}, "lastName": "Pro", "li": ["A", "b", 3]} <class 'str'>

可以发现,Python中都是使用单引号',JSON中都是使用双引号"

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

# 这是一个python 列表对象
py_list = [1, 2, 3]

print('Python对象:', end="")
print(py_list, end="\t")
print(type(py_list))

# 将一个 Python 对象转换成 json 字符串
json_str = json.dumps(py_list, sort_keys=True)

print('JSON字符串:', end="")
print(json_str, end="\t")
print(type(json_str))

--------------------------------------------------

# Output:
Python对象:[1, 2, 3] <class 'list'>
JSON字符串:[1, 2, 3] <class 'str'>
  1. 使用dump()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import json

py_dic = {
'firstName': 'Boii',
'j': {
'x': 1,
'y': "2",
'z': 3
},
"lastName": "Pro",
'li': ["A", 'b', 3]
}

# 将一个 Python 对象转换成 json 字符串,然后写入文件
with open('./py_dic.json', 'w', encoding='utf-8') as f:
json.dump(py_dic, f, sort_keys=True)

--------------------------------------------------

# Output:
没有输出,因为输出到文件中了

# py_dic.json
{"firstName": "Boii", "j": {"x": 1, "y": "2", "z": 3}, "lastName": "Pro", "li": ["A", "b", 3]}

有些教程中直接使用open()打开一个文件对象,然后将文件对象作为参数传入dump(),却没有使用close()关闭文件对象。这是错误的,会造成文件对象一直没有关闭而持续占用计算机资源。

解决方法:要么手动调用close()方法,要么用with语句

1
2
3
4
5
6
7
8
f = open('./py_dic.json', 'w', encoding='utf-8')
json.dump(py_dic, f, sort_keys=True)
f.close()



with open('./py_dic.json', 'w', encoding='utf-8') as f:
json.dump(py_dic, f, sort_keys=True)

JSON -> Python

json.load(fp, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)

json.loads(s, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)

  • fp:文件对象,要写入的文件
  • object_hook:是一个可选的函数,它会被调用于每一个解码出的对象字面量(即一个 dict)。object_hook 的返回值会取代原本的 dict。这一特性能够被用于实现自定义解码器(如 JSON-RPC 的类型提示)。
  • parse_floatparse_intparse_constantobject_pairs_hook:都是编码解码器需要的参数
  1. 使用loads()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import json

Str = '{"name": "Boii", "age": 30, "tel":["13800000000", "13100880088"], "isonly":true}'

print('JSON字符串:', end="")
print(Str, end='\t')
print(type(Str))

# 将一个 json 字符串 转换成 Python 对象
pythonObj = json.loads(Str)

print('Python对象:', end="")
print(pythonObj, end='\t')
print(type(pythonObj))
--------------------------------------------------

# Output:

JSON字符串:{"name": "Boii", "age": 30, "tel":["13800000000", "13100880088"], "isonly":true} <class 'str'>
Python对象:{'name': 'Boii', 'age': 30, 'tel': ['13800000000', '13100880088'], 'isonly': True} <class 'dict'>

可以发现,Python中都是使用单引号',JSON中都是使用双引号"

  1. 使用load()从json文件中读取转换成Python对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# py.json
{"firstName": "Boii", "j": {"x": 2, "y": "2", "z": 3}, "lastName": "Pro", "li": ["A", "b", 3]}

# j2p.py
import json

with open('./j2p.py', 'r', encoding='utf-8') as f:
pythonObj = json.load(f)
print('Python对象:', end="")
print(pythonObj)
print(type(pythonObj))

--------------------------------------------------

# Output:
Python对象:{'firstName': 'Boii', 'j': {'x': 1, 'y': '2', 'z': 3}, 'lastName': 'Pro', 'li': ['A', 'b', 3]}
<class 'dict'>

总结

1
2
3
4
5
6
7
# Writing JSON data
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)

哔哔