|
|
|
|
|
本文將介紹Phyton如何將JSON數(shù)據(jù)轉(zhuǎn)換為自定義Python對象,即,解析并將JSON轉(zhuǎn)換為Python類。
Python使用json.load() 和 json.loads() 方法從文件或字符串加載 JSON 數(shù)據(jù)時(shí),它會返回一個(gè)dict
。如果我們將 JSON 數(shù)據(jù)直接加載到我們的自定義類型中,我們可以更輕松地操作和使用它。有多種方法可以實(shí)現(xiàn)這一點(diǎn),你可以選擇你認(rèn)為對你的問題更有用的方式。讓我們看看如何將 JSON 字符串反序列化為自定義 Python 對象。
Python如何將JSON轉(zhuǎn)換為自定義Python對象
使用namedtuple和object_hook將JSON轉(zhuǎn)換為自定義Python對象
我們可以使用json.loads()和json.load()方法中的object_hook
參數(shù),這是一個(gè)可選函數(shù),將使用任何對象文字解碼的結(jié)果(字典dict
)調(diào)用,所以當(dāng)我們執(zhí)行json.loads()
時(shí),object_hook
的返回值將用字典dict
代替。使用此功能,我們可以實(shí)現(xiàn)自定義解碼器。
正如我們所知json.load()
和json.loads()
方法將 JSON 轉(zhuǎn)換為dict
對象,因此我們需要?jiǎng)?chuàng)建一個(gè)自定義函數(shù),我們可以在其中轉(zhuǎn)換dict
為自定義 Python 類型。并將這個(gè)新創(chuàng)建的函數(shù)傳遞給json.loads方法的object_hook參數(shù)。所以我們可以在解碼JSON時(shí)獲得自定義類型。
namedtuple是集合模塊下的類。與字典類型對象一樣,它包含鍵并映射到某些值。在這種情況下,我們可以使用鍵和索引訪問元素。
讓我們先看一個(gè)簡單的例子,然后我們才能進(jìn)入實(shí)際的例子。在此示例中,我們將學(xué)生JSON數(shù)據(jù)轉(zhuǎn)換為自定義學(xué)生類類型。
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
如你所見,我們將 JSON 字符串格式的 JSON 數(shù)據(jù)轉(zhuǎn)換為自定義 Python 對象 Student?,F(xiàn)在,我們可以使用 dot(.) 運(yùn)算符訪問其成員。
現(xiàn)在,讓我們看看使用復(fù)雜 Python 對象的實(shí)時(shí)場景。我們需要將自定義 Python 對象轉(zhuǎn)換為 JSON。此外,我們想從 JSON 構(gòu)造一個(gè)自定義的 Python 對象。
在這個(gè)例子中,我們使用了兩個(gè)類Student和Marks。Marks類是Student類的成員。
現(xiàn)在讓我們看看例子。
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
使用 types.SimpleNamespace 和 object_hook 將 JSON 轉(zhuǎn)換為自定義 Python 對象
我們可以用types.SimpleNamespace
作為 JSON 對象的容器。與命名元組解決方案相比,它具有以下優(yōu)勢:
在本例中,我們將使用types.SimpleNamespace
和object_hook
將 JSON 數(shù)據(jù)轉(zhuǎn)換為自定義 Python 對象。
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 74
使用 JSONDecoder 類的對象解碼將 JSON 數(shù)據(jù)轉(zhuǎn)換為自定義 Python 對象
我們可以使用 json模塊的json.JSONDecoder
類來專門進(jìn)行 JSON 對象解碼,這里我們可以將 JSON 對象解碼為自定義的 Python 類型。
我們需要在一個(gè)類中創(chuàng)建一個(gè)新函數(shù),該函數(shù)將負(fù)責(zé)檢查 JSON 字符串中的對象類型,在獲取 JSON 數(shù)據(jù)中的正確類型后,我們可以構(gòu)建我們的對象。
讓我們看看例子。
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
<class '__main__.Student'>
Student Details
1 Ault kelly 78
使用 jsonpickle 模塊將 JSON 數(shù)據(jù)轉(zhuǎn)換為自定義 Python 對象
jsonpickle 是一個(gè) Python 庫,旨在處理復(fù)雜的 Python 對象。你可以使用 jsonpickle 對復(fù)雜的 Python 和 JSON 數(shù)據(jù)進(jìn)行序列化和反序列化。
Python 內(nèi)置的 JSON 模塊只能處理 Python 原語。對于任何自定義 Python 對象,我們都需要編寫自己的 JSONEncoder 和 Decoder。
使用 jsonpickle 我們將執(zhí)行以下操作:
現(xiàn)在,讓我們看看將 JSON 數(shù)據(jù)轉(zhuǎn)換為自定義 Python 對象的 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)
輸出:
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
新建一個(gè)對象,將結(jié)果字典作為map傳遞,將JSON數(shù)據(jù)轉(zhuǎn)換為自定義的Python對象
正如我們所知json.loads()
和json.load()
方法返回一個(gè)dict
對象。我們可以通過將dict
對象作為參數(shù)傳遞給 Student 對象構(gòu)造函數(shù)來構(gòu)造一個(gè)新的自定義對象。即,我們可以將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: <class '__main__.Student'>
Student Details
1 Emma
總結(jié)
本文通過幾種方法,介紹了Python如何將JSON轉(zhuǎn)換為自定義Python對象/Python類。