淘先锋技术网

首页 1 2 3 4 5 6 7

前言:

本文默认你了解json,对Python的json模块也有基本的了解

正文

1. 总结

Python的json模块解决的问题是三种格式的转换:

  1. 字符串
  2. Python对象
  3. 文件

Python对象包括:
所有Python基本数据类型,列表,元组,字典,自己定义的类,等等等等,当然除了字符串

Python的json模块其实没有多少内容,
说起来的话常用的一共有4个方法:

  1. json.dumps
  2. json.dump
  3. json.loads
  4. json.load

你可以认为这4个方法就是json模块的全部
这四个方法实现了三种格式之间的互相转换:
python3的json模块图文实战总结

2. 互相转化:

这四个方法之间有如下关系

Python对象与字符串互相转换:

python对象 ⇢ \dashrightarrow 字符串:json.dumps
字符串 ⇢ \dashrightarrow Python对象:json.loads

Python对象与数据文件互相转换:

json文件 ⇢ \dashrightarrow Python对象:json. load
Python对象 ⇢ \dashrightarrow json文件:json.dump

其他类型转Python对象:

load(s)

其他类型写入json文件:

dump

实战

只有Python对象才可以转字符串,而文件是不可以直接转字符串的

文件转字符串:load ⇢ \dashrightarrow dumps

有没有发现字符串转Python对象用loads,文件转Python对象用load,而字符串和Python对象转文件都是用dump
Because dump接收的是obj对象,我们可以看下dump方法定义是的签名:

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).
...
"""

第一参数就是obj

OK,问题又来了,我们看下dumps方法定义时的签名:

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``.
...
"""

dumps方法接收的也是obj类型的对象,但是为什么文件不能直接转字符串呢?
因为dumps接收的obj对象需要进行json序列化,而在Python里文件的类型为TextIOWrapper,它没有进行json序列化。
大家可以看下dumpdumps方法定义的下面的注释,它们接收的obj对象都是需要进行json序列化的。:

Serialize ``obj`` to a JSON formatted ``str``

OK,问题又来了,我们应该怎么进行json序列化呢?
我们现在定义一个Person类:

class Person:
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

p = Person("马云", 54, "man")
print(json.dumps(p))

运行的时候会报错: Person没有进行JSON序列化:
python3的json模块图文实战总结_02Person定义一个JSON序列化的方法(其实就是类实例转换为字符串), 然后在调用的时候显式指定, 我们再试一下:

class Person:
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender


    def toJSON(self):
        return {
            "name": self.name,
            "age": self.age,
            "gender": self.gender
        }
p = Person("马云", 54, "man")
a = json.dumps(p, default=Person.toJSON, ensure_ascii=False)
print(a)

这样就好了:

python3的json模块图文实战总结_03
OK,那么我我们又怎么进行反序列化,把一个字符串反序列化成一个指定的类(而不是字典)呢?
很简单,也是定义一个方法用于把字符串转为类实例,然后在json.loads的时候指定就可以了,代码如下:

class Person:
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender


    def toJSON(self):
        return {
            "name": self.name,
            "age": self.age,
            "gender": self.gender
        }


    @staticmethod
    def parseJSON(dct):
        if isinstance(dct, dict):
            p = Person(dct["name"], int(dct['age']), dct['gender'])
            return p
        return dct
a = """{"name": "马云", "age": 54, "gender": "man"}"""
b = json.loads(a, object_hook=Person.parseJSON)
print(b)

打印结果:
python3的json模块图文实战总结_04