在 Python-JSON 中编码和解码自定义对象
我们知道JSON代表JavaScript Object Notation 。它是一种轻量级的数据交换格式,已成为最流行的网络数据交换媒介。它受欢迎的原因在于它既易于人类阅读,又易于机器解析和生成。此外,它是最广泛使用的 REST API 格式。
注意:有关详细信息,请参阅使用Python读取、写入和解析 JSON
入门
Python提供了一个内置的json
库来处理 JSON 对象。您只需在Python程序中使用以下行导入 JSON 模块并开始使用其功能。
import json
现在 JSON 模块提供了很多功能,我们将只讨论其中的两种方法。它们是转储和装载。将Python对象转换为 json 对象的过程称为JSON 序列化或编码,相反的过程,即将 json 对象转换为Python对象称为反序列化或解码
对于编码,我们使用json.dumps()
,对于解码,我们将使用json.loads()
。因此很明显,dumps 方法会将Python对象转换为序列化的 JSON字符串,而 loading 方法将从序列化的 JSON字符串中解析Python对象。
笔记:
- 这里值得一提的是,在序列化过程中创建的 JSON 对象只是一个Python字符串,这就是为什么您会发现本文中的术语“JSON 对象”和“JSON字符串”可以互换使用
- 同样重要的是要注意 JSON 对象对应于Python中的 Dictionary 。因此,当您使用加载方法时,默认返回Python字典(除非您按照本文自定义解码部分中的讨论更改此行为)
例子:
import json
# A basic python dictionary
py_object = {"c": 0, "b": 0, "a": 0}
# Encoding
json_string = json.dumps(py_object)
print(json_string)
print(type(json_string))
# Decoding JSON
py_obj = json.loads(json_string)
print()
print(py_obj)
print(type(py_obj))
输出:
{"c": 0, "b": 0, "a": 0}
{'c': 0, 'b': 0, 'a': 0}
虽然我们在上面看到的是一个非常简单的例子。但是你有没有想过在自定义对象的情况下会发生什么?在这种情况下,上面的代码将不起作用,我们将收到类似的错误 - TypeError: Object of type SampleClass is not JSON serializable 。那么该怎么办?不用担心,我们将进入以下部分。
编码和解码自定义对象
在这种情况下,我们需要付出更多的努力来让它们序列化。让我们看看如何做到这一点。假设我们有一个用户定义的类Student ,我们想让它成为 JSON 可序列化的。最简单的方法是在我们的类中定义一个方法,该方法将提供我们类实例的 JSON 版本。
例子:
import json
class Student:
def __init__(self, name, roll_no, address):
self.name = name
self.roll_no = roll_no
self.address = address
def to_json(self):
'''
convert the instance of this class to json
'''
return json.dumps(self, indent = 4, default=lambda o: o.__dict__)
class Address:
def __init__(self, city, street, pin):
self.city = city
self.street = street
self.pin = pin
address = Address("Bulandshahr", "Adarsh Nagar", "203001")
student = Student("Raju", 53, address)
# Encoding
student_json = student.to_json()
print(student_json)
print(type(student_json))
# Decoding
student = json.loads(student_json)
print(student)
print(type(student))
输出:
{
“name”: “Raju”,
“roll_no”: 53,
“address”: {
“city”: “Bulandshahr”,
“street”: “Adarsh Nagar”,
“pin”: “203001”
}
}
{‘name’: ‘Raju’, ‘roll_no’: 53, ‘address’: {‘city’: ‘Bulandshahr’, ‘street’: ‘Adarsh Nagar’, ‘pin’: ‘203001’}}
实现此目的的另一种方法是创建一个扩展JSONEncoder的新类,然后将该类用作dumps方法的参数。
例子:
import json
from json import JSONEncoder
class Student:
def __init__(self, name, roll_no, address):
self.name = name
self.roll_no = roll_no
self.address = address
class Address:
def __init__(self, city, street, pin):
self.city = city
self.street = street
self.pin = pin
class EncodeStudent(JSONEncoder):
def default(self, o):
return o.__dict__
address = Address("Bulandshahr", "Adarsh Nagar", "203001")
student = Student("Raju", 53, address)
# Encoding custom object to json
# using cls(class) argument of
# dumps method
student_JSON = json.dumps(student, indent = 4,
cls = EncodeStudent)
print(student_JSON)
print(type(student_JSON))
# Decoding
student = json.loads(student_JSON)
print()
print(student)
print(type(student))
输出:
{
“name”: “Raju”,
“roll_no”: 53,
“address”: {
“city”: “Bulandshahr”,
“street”: “Adarsh Nagar”,
“pin”: “203001”
}
}
{‘name’: ‘Raju’, ‘roll_no’: 53, ‘address’: {‘city’: ‘Bulandshahr’, ‘street’: ‘Adarsh Nagar’, ‘pin’: ‘203001’}}
对于自定义解码,如果我们想将 JSON 转换为其他Python对象(即不是默认字典),有一种非常简单的方法是使用load方法的object_hook参数。我们需要做的就是定义一个方法,该方法将定义我们希望如何处理数据,然后将该方法作为 object_hook 参数发送到加载方法,请参见给定代码。此外,load 的返回类型将不再是Python字典。无论我们作为object_hook 传入的方法的返回类型是什么,它也将成为loads 方法的返回类型。这意味着在以下示例中,复数将是返回类型。
import json
def as_complex(dct):
if '__complex__' in dct:
return complex(dct['real'], dct['imag'])
return dct
res = json.loads('{"__complex__": true, "real": 1, "imag": 2}',
object_hook = as_complex)
print(res)
print(type(res))
输出:
(1+2j)
在评论中写代码?请使用 ide.geeksforgeeks.org,生成链接并在此处分享链接。