|
|
|
|
|
本文將介紹Phyton如何將JSON數(shù)據(jù)轉(zhuǎn)換為自定義Python對象,即,解析并將JSON轉(zhuǎn)換為Python類。
Python使用json.load() 和 json.loads() 方法從文件或字符串加載 JSON 數(shù)據(jù)時,它會返回一個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ù),這是一個可選函數(shù),將使用任何對象文字解碼的結(jié)果(字典dict
)調(diào)用,所以當(dāng)我們執(zhí)行json.loads()
時,object_hook
的返回值將用字典dict
代替。使用此功能,我們可以實(shí)現(xiàn)自定義解碼器。
正如我們所知json.load()
和json.loads()
方法將 JSON 轉(zhuǎn)換為dict
對象,因此我們需要創(chuàng)建一個自定義函數(shù),我們可以在其中轉(zhuǎn)換dict
為自定義 Python 類型。并將這個新創(chuàng)建的函數(shù)傳遞給json.loads方法的object_hook參數(shù)。所以我們可以在解碼JSON時獲得自定義類型。
namedtuple是集合模塊下的類。與字典類型對象一樣,它包含鍵并映射到某些值。在這種情況下,我們可以使用鍵和索引訪問元素。
讓我們先看一個簡單的例子,然后我們才能進(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í)時場景。我們需要將自定義 Python 對象轉(zhuǎn)換為 JSON。此外,我們想從 JSON 構(gòu)造一個自定義的 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 轉(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 類型。
我們需要在一個類中創(chuàng)建一個新函數(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 是一個 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
新建一個對象,將結(jié)果字典作為map傳遞,將JSON數(shù)據(jù)轉(zhuǎn)換為自定義的Python對象
正如我們所知json.loads()
和json.load()
方法返回一個dict
對象。我們可以通過將dict
對象作為參數(shù)傳遞給 Student 對象構(gòu)造函數(shù)來構(gòu)造一個新的自定義對象。即,我們可以將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類。