json文件的使用方式
json 全称 JavaScript object notation,是一种轻量级的数据交换格式。python中的json模块提供了json数据的处理功能。
python中最常用的基本数据结构之一就是字典,其典型结构如下:
d = {
'a': 123,
'b': {
'x': ['A', 'B', 'C']
}
}
而json的结构如下:
{
"a": 123,
"b": {
"x": ["A", "B", "C"]
}
}
可以看到,dict和json非常接近,而python中的json库提供的主要功能,也是两者之间的转化。json中,字符串只能放在双引号中。如果被处理的python字符串是包含在双引号中的,那么json中的双引号就需要转义,否则会报错。
import json
jo = json.loads('{"a": 123}')
jo = json.loads("{\"a\": 123}")
json read
今天出的问题原来是把py文件命名成了模块名而导致的。
对于内容是json数据的bytes和bytearray,json.loads方法也可以处理:
import json
json.loads('{"a": 123}'.encode('UTF-8'))
{'a': 123}
json.loads(bytearray('{"a": 123}', 'UTF-8'))
{'a': 123}
数据类型转换
json可以表示四种主类型数据:
- 字符串 string
- 数字 number
- 布尔值 boolean
- 空值 null
以及两种数据结构:
- 对象 object
- 数组 array
默认实现中,json和python之间的数据转换关系对应如下
json | python |
---|---|
object | dict |
array | list |
string | str |
number(int) | int |
number(real) | float |
true | True |
null | None |
NaN | float(‘nan’) |
Infinity | float(‘inf’) |
-Infinity | float(’-inf’) |
示例如下:
json_exp = """
{
"obj":{
"str":"abc",
"int": 123,
"float": -3.1415926,
"bool_true": true,
"bool false": false,
"null": null,
"array": [1, 2, [3]],
"NaN": NaN,
"Infinity": Infinity,
"-Infinity": -Infinity
}
}
"""
jo = json.loads(json_exp)
print(jo)
print(jo['obj']['array'][2][0])
stdout:
C:\Users\winter\Anaconda2\envs\tensorflow\python.exe E:/PycharmProjects/CONSOLE/Json.py
{'obj': {'str': 'abc', 'int': 123, 'float': -3.1415926, 'bool_true': True, 'bool false': False, 'null': None, 'array': [1, 2, [3]], 'NaN': nan, 'Infinity': inf, '-Infinity': -inf}}
3
自定义json对象转换类型
json.loads()
默认将json中的对象数据转化为dict
类型,object_hook
参数可以用来改变构造出的对象。object_hook
接受一个函数,函数的输入参数为json中对象数据转换出的dict
对象。当json中的对象有嵌套时,json.loads()
方法会按照深度优先的方式遍历对象树,将各层的对象数据传递给object_hook
叶节点的json对象构造出的python对象,会作为父节点的一个值,传递给父节点的object_hook方法。
class MyJSONObj:
def __init__(self, x):
self.x = x
def my_json_obj_hook(data):
print('obj_hook data: %s' % data)
return MyJSONObj(data['x'])
result = json.loads('{"x": {"x": 11, "y": 12}, "y": {"x": 21, "y":22}}', object_hook=my_json_obj_hook)
print(type(result), result.x.x)
stdout:
obj_hook data: {'x': 11, 'y': 12}
obj_hook data: {'x': 21, 'y': 22}
obj_hook data: {'x': <__main__.MyJSONObj object at 0x000001BCDCA8DDD8>, 'y': <__main__.MyJSONObj object at 0x000001BCDCA8DE10>}
<class '__main__.MyJSONObj'> 11
类似地,还有自定义json数字转换类型:
json | para |
---|---|
obj | object_hook |
float | parse_float |
int | parse_int |
NaN… | parse_constant |
非对象值
json.loads('123')
123
json.loads('null')
json.loads('NaN')
nan
重复键名
在同一级json对象中,不应当出现重复的键名。不过,json规范中没有给出这种情况的处理标准,在json.loads()
中,当json数据中有重复键名时,则前面的键名会被后面的键名覆盖。
json.loads('{"a": 123, "b": "ABC", "a": 321}')
{'a': 321, 'b': 'ABC'}
处理json数据文件
json.load(json_file)
除了文件类型对象,只要是实现了read
方法的类文件对象,也可以作为json.load()
的参数。
json write
json.dumps(python_string)
json.dumps({'a': 123, 'b':234})
'{"a": 123, "b": 234}'
ps.json.dumps()
的ensure_ascii
参数用来控制生成的json字符串的编码,默认值为True
,此时,所有非ascii编码均会进行转义。更改为False后会保持原有编码UTF-8
。
json.dumps({'a': 123, '张晓龙':234})
'{"a": 123, "\\u5f20\\u6653\\u9f99": 234}'
json.dumps({'a': 123, '张晓龙':234}, ensure_ascii=False)
'{"a": 123, "张晓龙": 234}'
json字符串输出格式
json.dumps()
方法的indent
参数可以用来控制json字符串的换行和缩进效果。
indent | 效果 | example |
---|---|---|
None | 咩有缩进效果 | {"a": 123, "b": {"x": 321, "y": "ABC"}} |
<=0 | 换行 | 示例1 |
正整数 | 以指定数量的空格为单位在对象层次间进行缩进 | 示例2 |
str | 以str内容为单位进行缩进 | 示例3 |
示例1:
print(json.dumps(jc, indent=0))
{
"a": 123,
"b": {
"x": 321,
"y": "ABC"
}
}
print(json.dumps(jc, indent=-2))
{
"a": 123,
"b": {
"x": 321,
"y": "ABC"
}
}
示例2:
print(json.dumps(jc, indent=1))
{
"a": 123,
"b": {
"x": 321,
"y": "ABC"
}
}
print(json.dumps(jc, indent=2))
{
"a": 123,
"b": {
"x": 321,
"y": "ABC"
}
}
示例3:
print(json.dumps(jc, indent='\t'))
{
"a": 123,
"b": {
"x": 321,
"y": "ABC"
}
}
print(json.dumps(jc, indent='long'))
{
long"a": 123,
long"b": {
longlong"x": 321,
longlong"y": "ABC"
long}
}
转换自定义Python对象
json.dumps
的默认实现只能转换Dictionary
类型的对象。如果想要转换自定义对象, 需要使用default
参数。这个参数接收一个函数,这个函数的参数是一个要转换的Python对象, 返回值是能够表示这个Python对象的Dictionary对象。default函数会从对象引用树的顶层开始, 逐层遍历整个对象引用树。因此,不用自己实现对象树的遍历逻辑,只需要处理当前层次的对象。 如下例所示:
class MyClass:
def __init__(self, x, y):
self.x = x
self.y = y
def my_default(o):
if isinstance(o, MyClass):
print('%s.y: %s' % (type(o), o.y))
return {'x': o.x, 'y': o.y}
print(o)
return o
obj = MyClass(x=MyClass(x=1, y=2), y=11)
jo = json.dumps(obj, default=my_default)
print(jo)
stdout:
C:\Users\winter\Anaconda2\envs\tensorflow\python.exe E:/PycharmProjects/CONSOLE/Json.py
<class '__main__.MyClass'>.y: 11
<class '__main__.MyClass'>.y: 2
{"x": {"x": 1, "y": 2}, "y": 11}
写入json文件
json_exp = """
{
"obj":{
"str":"abc",
"int": 123,
"float": -3.1415926,
"bool_true": true,
"bool false": false,
"null": null,
"array": [1, 2, 3]
}
}
"""
json_exp = json.loads(json_exp)
print(json_exp)
jo = json.dumps(json_exp, indent='\t')
print(jo)
with open('diy.json', 'w') as f:
json.dump(json_exp, f, indent='\t')
diy.json
{
"obj": {
"str": "abc",
"int": 123,
"float": -3.1415926,
"bool_true": true,
"bool false": false,
"null": null,
"array": [
1,
2,
3
]
}
}