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