📅  最后修改于: 2020-09-01 07:21:47             🧑  作者: Mango
在以前的章节中,我们介绍了Python 的内置json模块只能处理Python基本数据类型,即将Python基本数据类型进行Json序列化。
当您尝试编码定制Python对象成JSON格式,您收到一个类型错误:Object of type SampleClass is not JSON serializable
。
因此,我们将在此介绍如何将任意Python对象序列化为JSON,以便您可以将任何自定义Python对象转换为JSON格式的数据。
大致介绍四种方法:
toJSON()
方法将对象序列化为Jsondict
使对象序列化为JsonPython json模块具有JSONEncoder类。如果您想要更丰富的自定义输出,则可以扩展它。即您将继承JSONEncoder子类,以便可以实现自定义JSON序列化。
JSON模块的json.dump和json.jumps方法有一个cls
kwarg。使用此参数,您可以传递自定义JSON编码器,该编码器告诉json.dump()
或json.dumps()
方法如何将您的对象编码为JSON格式的数据。默认的JSONEncoder类具有一个default()
在执行时将使用的方法JSONEncoder.encode(object)
。此方法仅将基本类型转换为JSON。
您的自定义JSONEncoder子类将覆盖该default()
方法以序列化其他类型。用cls
kwarg in json.dumps()
方法指定它;否则,将使用默认的JSONEncoder。
import json
from json import JSONEncoder
class Employee:
def __init__(self, name, salary, address):
self.name = name
self.salary = salary
self.address = address
class Address:
def __init__(self, city, street, pin):
self.city = city
self.street = street
self.pin = pin
# subclass JSONEncoder
class EmployeeEncoder(JSONEncoder):
def default(self, o):
return o.__dict__
address = Address("Alpharetta", "7258 Spring Street", "30004")
employee = Employee("John", 9000, address)
print("Printing to check how it will look like")
print(EmployeeEncoder().encode(employee))
print("Encode Employee Object into JSON formatted Data using custom JSONEncoder")
employeeJSONData = json.dumps(employee, indent=4, cls=EmployeeEncoder)
print(employeeJSONData)
# Let's load it using the load method to check if we can decode it or not.
print("Decode JSON formatted Data")
employeeJSON = json.loads(employeeJSONData)
print(employeeJSON)
现在我们查看输出结果:
Printing to check how it will look like
{"name": "John", "salary": 9000, "address": {"city": "Alpharetta", "street": "7258 Spring Street", "pin": "30004"}}
Encode Object into JSON formatted Data using custom JSONEncoder
{
"name": "John",
"salary": 9000,
"address": {
"city": "Alpharetta",
"street": "7258 Spring Street",
"pin": "30004"
}
}
Decode JSON formatted Data
{'name': 'John', 'salary': 9000, 'address': {'city': 'Alpharetta', 'street': '7258 Spring Street', 'pin': '30004'}}
值得注意:
default()
方法JSONEncoder
,因此我们能够将自定义Python对象转换为JSON。注意:如果您还想将JSON解码回Custom Python对象,请参考将JSON解码到Custom Python 对象,而不是解码为字典。
一个简单直接的解决方案,我们还可以在该类中实现序列化器方法,从而不需要编写自定义JSONEncoder。
import json
class Employee:
def __init__(self, name, salary, address):
self.name = name
self.salary = salary
self.address = address
def toJson(self):
return json.dumps(self, default=lambda o: o.__dict__)
class Address:
def __init__(self, city, street, pin):
self.city = city
self.street = street
self.pin = pin
address = Address("Alpharetta", "7258 Spring Street", "30004")
employee = Employee("John", 9000, address)
print("Encode into JSON formatted Data")
employeeJSONData = json.dumps(employee.toJson(), indent=4)
print(employeeJSONData)
# Let's load it using the load method to check if we can decode it or not.
print("Decode JSON formatted Data")
employeeJSON = json.loads(employeeJSONData)
print(employeeJSON)
此时的输出结果如下:
Encode into JSON formatted Data
"{\"name\": \"John\", \"salary\": 9000, \"address\": {\"city\": \"Alpharetta\", \"street\": \"7258 Spring Street\", \"pin\": \"30004\"}}"
Decode JSON formatted Data
{"name": "John", "salary": 9000, "address": {"city": "Alpharetta", "street": "7258 Spring Street", "pin": "30004"}}
注意事项:
注意:如果您还想将JSON解码回Custom Python对象,请参考将JSON解码到Custom Python对象,而不是字典。
jsonpickle是一个Python库,目的是与复杂的Python对象一起使用完成复杂的功能。您可以使用jsonpickle将复杂的Python对象序列化为JSON。反之,也可以从JSON反序列化到复杂的Python对象。
如您所知,Python 的内置json模块只能处理Python原语类型(例如,字典,列表,字符串,数字,None等), jsonpickle建立在这些库之上,并允许将更复杂的数据结构序列化为JSON。
主要步骤:
pip install jsonpickle
jsonpickle.encode(object)
import json
import jsonpickle
from json import JSONEncoder
class Employee(object):
def __init__(self, name, salary, address):
self.name = name
self.salary = salary
self.address = address
class Address(object):
def __init__(self, city, street, pin):
self.city = city
self.street = street
self.pin = pin
address = Address("Alpharetta", "7258 Spring Street", "30004")
employee = Employee("John", 9000, address)
print("Encode Object into JSON formatted Data using jsonpickle")
empJSON = jsonpickle.encode(employee, unpicklable=False)
print("Writing JSON Encode data into Python String")
employeeJSONData = json.dumps(empJSON, indent=4)
print(employeeJSONData)
print("Decode JSON formatted Data using jsonpickle")
EmployeeJSON = jsonpickle.decode(employeeJSONData)
print(EmployeeJSON)
# Let's load it using the load method to check if we can decode it or not.
print("Load JSON using loads() method")
employeeJSON = json.loads(EmployeeJSON)
print(employeeJSON)
输出如下:
Encode Object into JSON formatted Data using jsonpickle
Writing JSON Encode data into Python String
"{\"address\": {\"city\": \"Alpharetta\", \"pin\": \"30004\", \"street\": \"7258 Spring Street\"}, \"name\": \"John\", \"salary\": 9000}"
Decode JSON formatted Data using jsonpickle
{"address": {"city": "Alpharetta", "pin": "30004", "street": "7258 Spring Street"}, "name": "John", "salary": 9000}
Load JSON using loads() method
{'address': {'city': 'Alpharetta', 'pin': '30004', 'street': '7258 Spring Street'}, 'name': 'John', 'salary': 9000}
注意事项:
unpicklable=False
那么些数据解码回Object。如果希望将JSON解码回Employee Object,需设置unpicklable=True
如果不想编写自定义编码器,也不想使用jsonpickle,则可以使用这种解决方案。如果您的class不复杂,则此解决方案有效。对于复杂的类/对象,您将必须显式设置一些keys。
import json
class Employee(dict):
def __init__(self, name, age, salary, address):
dict.__init__(self, name=name, age=age, salary=salary, address=address)
class Address(dict):
def __init__(self, city, street, pin):
dict.__init__(self, city=city, street=street, pin=pin)
address = Address("Alpharetta", "7258 Spring Street", "30004")
employee = Employee("John", 36, 9000, address)
print("Encode into JSON formatted Data")
employeeJSON = json.dumps(employee)
print(employeeJSON)
# Let's load it using the load method to check if we can decode it or not.
print("Decode JSON formatted Data")
employeeJSONData = json.loads(employeeJSON)
print(employeeJSONData)
输出如下:
Encode into JSON formatted Data
{"name": "John", "age": 36, "salary": 9000, "address": {"city": "Alpharetta", "street": "7258 Spring Street", "pin": "30004"}}
Decode JSON formatted Data
{'name': 'John', 'age': 36, 'salary': 9000, 'address': {'city': 'Alpharetta', 'street': '7258 Spring Street', 'pin': '30004'}}
此方法对于不愿意修改json.dumps(obj)
的小伙伴是很有用。 即您只需按json.dumps(obj)
原样调用。
——>>>>>该节内容到此结束了,希望提供的四种方法能对小伙伴们提供帮助