一般的场景是这样:

标准的json(接口返回的) ==>(需要转换成) Python字典, 用json.loads

python字典格式  ==>(需要转换成) 标准的json, 用json.dumps

Python处理json的函数有四个:dumps、dump、loads、load

dumps

源码定义如下:

1
2
3
4
5
def 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):
    """Serialize ``obj`` to a JSON formatted ``str``.
    ....

注释Serialize ``obj`` to a JSON formatted ``str说明了该函数的作用: 将obj序列化为str类型的JSON格式。

dumps至少接收一个obj参数,obj是什么呢,就是dict、list、tuple、str等这些python的数据类型。

比如我定义一个dict类型的obj

1
2
3
4
5
6
7
8
obj = {
    "msgtype": "markdown",
    "markdown": {
        "title": "title",
        "value": 0,
        "text": None
    }
}

注意,这是一个python的字典(dict)类型,所以只有python知道怎么处理。如果想让HTTP直接以POST方式处理,肯定是不行的(但像requests库有内置的 JSON解码器,所以可以直接帮你处理),需要先转换成HTTP能够理解的格式,即json。

使用json.dumps(obj)后,就会变成标准的json格式了。但是注意,json.dumps(obj)本身是str类型。

1
2
3
4
5
6
7
8
obj_to_json = json.dumps(obj)

print(obj_to_json)
print(type(obj_to_json))

#输出
{"msgtype": "markdown", "markdown": {"title": "title", "value": 0, "text": null}}
<class 'str'>

所以dumps的使用场景可以理解为当自己需要构造一个json时使用。

dump

源码定义如下:

1
2
3
4
5
6
def 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):
    """Serialize ``obj`` as a JSON formatted stream to ``fp`` (a
    ``.write()``-supporting file-like object).
    ...

dump和dumps作用是一样的,只不过dump是必须要将序列化的结果保存到IO类的对象里。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 序列化并保存到文件
with open('obj.txt', 'w') as f:
    json.dump(obj, f)

# 读取结果
with open('obj.txt', 'r') as f:
    print(f.read())

#输出
{"msgtype": "markdown", "markdown": {"title": "title", "value": 0, "text": null}}

注意obj是字典类型,所以当用load反序列化后的结果还是字典。

loads

源码定义如下:

1
2
3
4
def loads(s, *, encoding=None, cls=None, object_hook=None, parse_float=None,
        parse_int=None, parse_constant=None, object_pairs_hook=None, **kw):
    """Deserialize ``s`` (a ``str``, ``bytes`` or ``bytearray`` instance
    containing a JSON document) to a Python object.

当你从http地址(比如腾讯云api)请求一个地址后,对方都会返回一个response,基本都是json数据(注意是str类型,相应的SDK里会有转换的方法)。如腾讯云的安全组下的某个api返回的内容

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
{
    "SecurityGroupSet":[
        {
            "SecurityGroupId":"sg-5u9jj0ec",
            "SecurityGroupName":"default",
            "SecurityGroupDesc":"System created security group",
            "ProjectId":"0","ALL",
            "IsDefault":true,
            "CreatedTime":"2021-01-07 15:54:13","ALL",
            "TagSet":[

            ]
        }
    ],
    "TotalCount":1,
    "RequestId":"284a79dd-8ef7-4d6e-936d-c9f7a5edc1b1","ALL"
}

这是print后的结果,实际的代码是resp.to_json_string(),使用loads函数获取某个字段的值(比如’CreatedTime’)如下:

1
2
3
4
5
resp_str = resp.to_json_string()

resp_dict = json.loads(resp_str)

print(resp_dict['SecurityGroupSet'][0]['CreatedTime'])

所以总结loads的使用场景是用于处理HTTP地址返回的json数据,转换为Python更具体的对象后(一般都是dict),Python就可以灵活处理了。

load

源码定义如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
def load(fp, *, cls=None, object_hook=None, parse_float=None,
        parse_int=None, parse_constant=None, object_pairs_hook=None, **kw):
    """Deserialize ``fp`` (a ``.read()``-supporting file-like object containing
    a JSON document) to a Python object.

    ....省略
    """
    return loads(fp.read(),
        cls=cls, object_hook=object_hook,
        parse_float=parse_float, parse_int=parse_int,
        parse_constant=parse_constant, object_pairs_hook=object_pairs_hook, **kw)

读取一个文件,然后反序列化为python对象

比如,反序列化上面dump的例子

1
2
3
4
5
with open('obj.txt', 'r') as f:
    print(json.load(f))

with open('obj.txt', 'r') as f:
    print(type(json.load(f)))