📅  最后修改于: 2020-09-27 03:27:32             🧑  作者: Mango
在本系列的学习中,我们学习过如何将Python自定义的类转为Json数据进行存储/传输。
在这次学习中,我们学习一下其相反的操作,如何解析Json的数据并转换为python对象。例如,您从AP/从文件中读取到JSON数据,希望将其转换为自定义的Employee类型。
当使用json.load/json.loads方法从文件或字符串加载JSON数据时,它将返回python Dict,如果能将JSON数据直接加载到我们的自定义类型中,我们可以轻松地进行操作和使用。
我们可以使用load/loads方法的object_hook
参数,其实可以理解因为一个函数,任何对象解码的结果都会调用它;因此,当我们执行时json.load的时候,object_hook
返回值将被使用,而不是Python的dict。
如何将JSON转换为自定义Python类型?
load/loads方法只能将JSON转换为dict
对象,因此我们需要创建一个自定义函数,并将这个新创建的函数传递给json.loads
方法的object_hook
参数。
namedtuple是一个类,位于Python的collections之中,像字典类型的对象一样,它包含键,并映射到某些值。在这种情况下,我们可以使用键和索引访问元素,如果对namedtuple不熟悉的小伙伴,可参考https://www.runoob.com/note/25726
我们以例子说明,将Student JSON数据转换为自定义的Student Class类型。
import json
from collections import namedtuple
from json import JSONEncoder
def customStudentDecoder(studentDict):
return namedtuple('X', studentDict.keys())(*studentDict.values())
#Assume you received this JSON response
studentJsonData = '{"rollNumber": 1, "name": "Emma"}'
# Parse JSON into an object with attributes corresponding to dict keys.
student = json.loads(studentJsonData, object_hook=customStudentDecoder)
print("After Converting JSON Data into Custom Python Object")
print(student.rollNumber, student.name)
我们看看打印的输出:真是我们想要的结果
After Converting JSON Data into Custom Python Object
1 Emma
现在,让我们学习稍微复杂示例。而且我们需要将自定义Python对象转换为JSON,同时我们想从JSON构造一个自定义Python对象。
在此示例中,我们使用两个类Student和Marks。Marks类是Student类的成员。
import json
from collections import namedtuple
from json import JSONEncoder
class Student:
def __init__(self, rollNumber, name, marks):
self.rollNumber, self.name, self.marks = rollNumber, name, marks
class Marks:
def __init__(self, english, geometry):
self.english, self.geometry = english, geometry
class StudentEncoder(JSONEncoder):
def default(self, o):
return o.__dict__
def customStudentDecoder(studentDict):
return namedtuple('X', studentDict.keys())(*studentDict.values())
marks = Marks(82, 74)
student = Student(1, "Emma", marks)
# dumps() produces JSON in native str format. if you want to writ it in file use dump()
studentJson = json.dumps(student, indent=4, cls=StudentEncoder)
print("Student JSON")
print(studentJson)
# Parse JSON into an object with attributes corresponding to dict keys.
studObj = json.loads(studentJson, object_hook=customStudentDecoder)
print("After Converting JSON Data into Custom Python Object")
print(studObj.rollNumber, studObj.name, studObj.marks.english, studObj.marks.geometry)
输出结果:
Student JSON
{
"rollNumber": 1,
"name": "Emma",
"marks": {
"english": 82,
"geometry": 74
}
}
After Converting JSON Data into Custom Python Object
1 Emma 82 74
上面两种方法,实现了将Json数据转化为Python中的namedtuple对象。
我们可以将types.SimpleNamespace
作为JSON对象的容器,与namedtuple相比,它具有以下优点:
from __future__ import print_function
import json
from json import JSONEncoder
try:
from types import SimpleNamespace as Namespace
except ImportError:
# Python 2.x fallback
from argparse import Namespace
class Student:
def __init__(self, rollNumber, name, marks):
self.rollNumber, self.name, self.marks = rollNumber, name, marks
class Marks:
def __init__(self, english, geometry):
self.english, self.geometry = english, geometry
class StudentEncoder(JSONEncoder):
def default(self, o): return o.__dict__
marks = Marks(82, 74)
student = Student(1, "Emma", marks)
# dumps() produces JSON in native str format. if you want to writ it in file use dump()
studentJsonData = json.dumps(student, indent=4, cls=StudentEncoder)
print("Student JSON")
print(studentJsonData)
# Parse JSON into an custom Student object.
studObj = json.loads(studentJsonData, object_hook=lambda d: Namespace(**d))
print("After Converting JSON Data into Custom Python Object using SimpleNamespace")
print(studObj.rollNumber, studObj.name, studObj.marks.english, studObj.marks.geometry)
输出如下:输出结果和之前的方法一致,但不需要创建一个类
Student JSON
{
"rollNumber": 1,
"name": "Emma",
"marks": {
"english": 82,
"geometry": 74
}
}
After Converting JSON Data into Custom Python Object using SimpleNamespace
1 Emma 82 7
可以使用json.JSONDecoder
对JSON对象解码,我们需要在类中创建一个新函数,该类将负责检查JSON字符串中的对象类型,在JSON数据中获取正确的类型之后,我们可以构造Object。
import json
class Student(object):
def __init__(self, rollNumber, name, marks):
self.rollNumber = rollNumber
self.name = name
self.marks = marks
def studentDecoder(obj):
if '__type__' in obj and obj['__type__'] == 'Student':
return Student(obj['rollNumber'], obj['name'], obj['marks'])
return obj
studentObj = json.loads('{"__type__": "Student", "rollNumber":1, "name": "Ault kelly", "marks": 78}',
object_hook=studentDecoder)
print("Type of decoded object from JSON Data")
print(type(studentObj))
print("Student Details")
print(studentObj.rollNumber, studentObj.name, studentObj.marks)
代码输出:
Type of decoded object from JSON Data
Student Details
1 Ault kelly 78
使用jsonpickle,我们将执行以下操作:
import json
import jsonpickle
from json import JSONEncoder
class Student(object):
def __init__(self, rollNumber, name, marks):
self.rollNumber = rollNumber
self.name = name
self.marks = marks
class Marks(object):
def __init__(self, english, geometry):
self.english = english
self.geometry = geometry
marks = Marks(82, 74)
student = Student(1, "Emma", marks)
print("Encode Object into JSON formatted Data using jsonpickle")
studentJSON = jsonpickle.encode(student)
print(studentJSON)
print("Decode and Convert JSON into Object using jsonpickle")
studentObject = jsonpickle.decode(studentJSON)
print("Object type is: ", type(studentObject))
print("Student Details")
print(studentObject.rollNumber, studentObject.name, studentObject.marks.english, studentObject.marks.geometry)
输出如下所示:此方法就不需要专门的写 JSONEncoder and Decoder了
Encode Object into JSON formatted Data using jsonpickle
{"marks": {"english": 82, "geometry": 74, "py/object": "__main__.Marks"}, "name": "Emma", "py/object": "__main__.Student", "rollNumber": 1}
Decode JSON formatted Data using jsonpickle
1 Emma 82 74
众所周知json.loads(),json.load()方法返回一个dict对象,那么我们可以通过将dict
对象作为参数传递给我们自己的一个函数,在函数中我们解码为我们自定义对象。
import json
from json import JSONEncoder
class Student(object):
def __init__(self, rollNumber, name, *args, **kwargs):
self.rollNumber = rollNumber
self.name = name
class StudentEncoder(JSONEncoder):
def default(self, o):
return o.__dict__
student = Student(1, "Emma")
# encode Object it
studentJson = json.dumps(student, cls=StudentEncoder, indent=4)
#Deconde JSON
resultDict = json.loads(studentJson)
print("Converting JSON into Python Object")
studentObj = Student(**resultDict)
print("Object type is: ", type(studentObj))
print("Student Details")
print(studentObj.rollNumber, studentObj.name)
输出如下:
Converting JSON into Python Object
Object type is:
Student Details
1 Emma
——-》》》关于讲Json数据转化为自定义对象的方法介绍就这么多,感谢你的阅读。