JSON(JavaScript对象表示法)是一种轻量级数据格式,用于数据交换。 在Python中具有用于编码和解码JSON数据的内置 json
模块。 只需导入它,就可以使用JSON数据了:
JSON的一些优点:
JSON作为“字节序列”存在,在我们需要通过网络传输(流)数据的情况下非常有用。
与XML相比,JSON小得多,可转化为更快的数据传输和更好的体验。
JSON非常文本友好,因为它是文本形式的,并且同时也是机器友好的。
JSON格式
{ "firstName" : "Jane" , "lastName" : "Doe" , "hobbies" : ["running" , "swimming" , "singing" ], "age" : 28 , "children" : [ { "firstName" : "Alex" , "age" : 5 }, { "firstName" : "Bob" , "age" : 7 } ] }
JSON支持基本类型(字符串,数字,布尔值)以及嵌套的数组和对象。 根据以下转换,将简单的Python对象转换为JSON:
Python 和 JSON 转换
从Python到JSON(序列化,编码)
使用 json.dumps()
方法将Python对象转换为JSON字符串。
import jsonperson = {"name" : "John" , "age" : 30 , "city" : "New York" , "hasChildren" : False , "titles" : ["engineer" , "programmer" ]} person_json = json.dumps(person) person_json2 = json.dumps(person, indent=4 , separators=("; " , "= " ), sort_keys=True ) print(person_json) print(person_json2)
{"name" : "John" , "age" : 30 , "city" : "New York" , "hasChildren" : false, "titles" :["engineer" , "programmer" ]} { "age" = 30 ; "city" = "New York" ; "hasChildren" = false; "name" = "John" ; "titles" = [ "engineer" ; "programmer" ] }
或将Python对象转换为JSON对象,然后使用 json.dump()
方法将其保存到文件中。
import jsonperson = {"name" : "John" , "age" : 30 , "city" : "New York" , "hasChildren" : False , "titles" : ["engineer" , "programmer" ]} with open('person.json' , 'w' ) as f: json.dump(person, f)
从JSON到Python(反序列化,解码)
使用 json.loads()
方法将JSON字符串转换为Python对象。 结果将是一个Python字典。
import jsonperson_json = """ { "age": 30, "city": "New York", "hasChildren": false, "name": "John", "titles": [ "engineer", "programmer" ] } """ person = json.loads(person_json) print(person)
{'age' : 30 , 'city' : 'New York' , 'hasChildren' : False , 'name' : 'John' , 'titles' : ['engineer' , 'programmer' ]}
或从文件加载数据,然后使用 json.load()
方法将其转换为Python对象。
import jsonwith open('person.json' , 'r' ) as f: person = json.load(f) print(person)
{'name' : 'John' , 'age' : 30 , 'city' : 'New York' , 'hasChildren' : False , 'titles' : ['engineer' , 'programmer' ]}
使用自定义对象
编码
使用默认的 JSONEncoder
编码自定义对象将引发 TypeError
。 我们可以指定一个自定义的编码函数,该函数将类名和所有对象变量存储在字典中。 将此函数用作 json.dump()
方法中的 default
参数。
import jsondef encode_complex (z) : if isinstance(z, complex): return {z.__class__.__name__: True , "real" :z.real, "imag" :z.imag} else : raise TypeError(f"Object of type '{z.__class__.__name__} ' is not JSON serializable" ) z = 5 + 9j zJSON = json.dumps(z, default=encode_complex) print(zJSON)
{"complex" : true, "real" : 5.0 , "imag" : 9.0 }
你还可以创建一个自定义的 Encoder 类,并覆盖 default()
方法。 将其用于 json.dump()
方法中的 cls
参数,或直接使用编码器。
from json import JSONEncoderclass ComplexEncoder (JSONEncoder) : def default (self, o) : if isinstance(z, complex): return {z.__class__.__name__: True , "real" :z.real, "imag" :z.imag} return JSONEncoder.default(self, o) z = 5 + 9j zJSON = json.dumps(z, cls=ComplexEncoder) print(zJSON) zJson = ComplexEncoder().encode(z) print(zJSON)
{"complex" : true, "real" : 5.0 , "imag" : 9.0 } {"complex" : true, "real" : 5.0 , "imag" : 9.0 }
解码
可以使用默认 JSONDecoder 解码自定义对象,但是它将被解码为字典。 编写一个自定义解码函数,该函数将以字典作为输入,并在可以在字典中找到对象类名称的情况下创建自定义对象。 将此函数用于 json.load()
方法中的 object_hook
参数。
z = json.loads(zJSON) print(type(z)) print(z) def decode_complex (dct) : if complex.__name__ in dct: return complex(dct["real" ], dct["imag" ]) return dct z = json.loads(zJSON, object_hook=decode_complex) print(type(z)) print(z)
<class 'dict '> {'complex': True, 'real': 5.0, 'imag': 9.0} <class 'complex '> (5 +9j )
模板编码和解码函数
如果在 __init__
方法中提供了所有类变量,则此方法适用于所有自定义类。
class User : def __init__ (self, name, age, active, balance, friends) : self.name = name self.age = age self.active = active self.balance = balance self.friends = friends class Player : def __init__ (self, name, nickname, level) : self.name = name self.nickname = nickname self.level = level def encode_obj (obj) : """ 接受一个自定义对象,并返回该对象的字典表示形式。 此字典表示形式还包括对象的模块和类名称。 """ obj_dict = { "__class__" : obj.__class__.__name__, "__module__" : obj.__module__ } obj_dict.update(obj.__dict__) return obj_dict def decode_dct (dct) : """ 接受字典并返回与该字典关联的自定义对象。 它利用字典中的 "__module__" 和 "__class__" 元数据来了解要创建的对象类型。 """ if "__class__" in dct: class_name = dct.pop("__class__" ) module_name = dct.pop("__module__" ) module = __import__(module_name) class_ = getattr(module,class_name) obj = class_(**dct) else : obj = dct return obj user = User(name = "John" ,age = 28 , friends = ["Jane" , "Tom" ], balance = 20.70 , active = True ) userJSON = json.dumps(user,default=encode_obj,indent=4 , sort_keys=True ) print(userJSON) user_decoded = json.loads(userJSON, object_hook=decode_dct) print(type(user_decoded)) player = Player('Max' , 'max1234' , 5 ) playerJSON = json.dumps(player,default=encode_obj,indent=4 , sort_keys=True ) print(playerJSON) player_decoded = json.loads(playerJSON, object_hook=decode_dct) print(type(player_decoded))
{ "__class__" : "User" , "__module__" : "__main__" , "active" : true, "age" : 28 , "balance" : 20.7 , "friends" : [ "Jane" , "Tom" ], "name" : "John" } <class '__main__ .User '> { "__class__" : "Player" , "__module__" : "__main__" , "level" : 5 , "name" : "Max" , "nickname" : "max1234" } <class '__main__ .Player '>
GitHub repo: qiwihui/blog
Follow me: @qiwihui
Site: QIWIHUI