Khi lập trình Python, đối với các mô hình lớp có mối quan hệ phức tạp và lồng nhau thì việc xử lý dữ liệu sẽ gặp nhiều khó khăn nếu chúng ta không biết cách lưu các dữ liệu đang thao tác trên bộ nhớ RAM xuống ổ cứng để sử dụng lâu dài. Và đặc biệt chúng ta phải biết cách phục hồi dữ liệu từ ổ cứng lên bộ nhớ, đồng thời chúng ta phải biết mô hình hóa lại đối tượng và mối quan hệ giữa các đối tượng một cách chính xác.
Bạn hiểu nôm na như sau, trong thuật ngữ lập trình thì việc ghi dữ liệu từ bộ nhớ RAM xuống ổ cứng với một định dạng nào đó thì người ta gọi là Serialize. Và khi phục hồi dữ liệu từ Ổ cứng lên Bộ nhớ RAM và phục hồi lại mô hình hướng đối tượng thì được gọi là Deserialize.
Chúng ta phải biết cách lập trình để nó có thể hiểu được bất kỳ mô hình lớp hướng đối tượng nào, và bất kỳ mối quan hệ phức tạp nào, lồng bao nhiêu cấp đối tượng…
Để làm được điều này, Tui minh họa bài như dưới đây, đó là bài liên quan tới Danh mục và Sản phẩm có cấu trúc dự án trong Pycharm như sau:

Tui mô tả sơ lược:
- Thư mục “utils“: Sẽ chứa các thư viện để tái sử dụng, ở đây ta sẽ tạo lớp JsonFactory để làm nhiệm vụ Serialize và Deserialize.
- Thư mục “models“: Chứa tập các mô hình lớp đối tượng, các lớp này có mối quan hệ với nhau, cụ thể trong ví dụ này: 1 Categories sẽ có nhiều Category, và 1 Category sẽ có nhiều Product.
- Cuối cùng là thư mục “test“: Để minh họa cách thức sử dụng Serialize và Deserialize
- Thư mục “assets“: Dùng để lưu trữ dữ liệu của các đối tượng, nó sẽ được Serialize xuống ổ cứng với định dạng Json.
Bước 1: Ta tạo “JsonFactory.py” để làm 5 nhiệm vụ chính:
Tên Hàm | Ý nghĩa |
---|---|
register | Hàm này để cho các lớp đối tượng đăng ký Serialize và Deserialize |
parse_json | Hàm này để chuyển toàn bộ đối tượng và các mối quan hệ giữa các đối tượng qua định dạng json |
restore_object | Hàm này dùng để phục hồi lại đối tượng từ định dạng json |
serialize | Hàm này để lưu đối tượng xuống ổ cứng với định dạng json |
deserialize | Hàm này để phục hồi lại đối tượng khi biết được định dạng json trong ổ cứng |
Dưới đây là mã lệnh chi tiết:
import json
class JsonFactory(object):
mappings = {}
@classmethod
def class_mapper(clsself, d):
for keys, cls in clsself.mappings.items():
if keys.issuperset(d.keys()):
return cls(**d)
else:
raise ValueError('Unable to find a matching class for object: {!s}'.format(d))
@classmethod
def complex_handler(clsself, Obj):
if hasattr(Obj, '__dict__'):
return Obj.__dict__
else:
raise TypeError('Object of type %s with value of %s is not JSON serializable' % (type(Obj), repr(Obj)))
@classmethod
def register(clsself, cls):
clsself.mappings[frozenset(tuple([attr for attr, val in cls().__dict__.items()]))] = cls
return cls
@classmethod
def parse_json(clsself, obj):
return json.dumps(obj.__dict__, default=clsself.complex_handler, indent=4)
@classmethod
def restore_object(clsself, json_str):
return json.loads(json_str, object_hook=clsself.class_mapper)
@classmethod
def serialize(clsself, obj, path):
with open(path, 'w') as jfile:
jfile.writelines([clsself.parse_json(obj)])
return path
@classmethod
def deserialize(clsself, filepath):
result = None
with open(filepath, 'r') as jfile:
result = clsself.restore_object(jfile.read())
return result
Bước 2: Tạo các lớp hướng đối tượng và các mối quan hệ, ví dụ như lớp Product, lớp Category và lớp Categories:
Lớp Product coding như sau:
from utils.JsonFactory import JsonFactory
@JsonFactory.register
class Product(object):
def __init__(self,product_id=None,product_name=None,unit_price=None):
self.product_id=product_id
self.product_name=product_name
self.unit_price=unit_price
def __str__(self):
return f"{self.product_id}\t{self.product_name}\t{self.unit_price}"
Lớp Product ở trên, Tui khai báo có 3 thuộc tính: product_id, product_name và unit_price. Đồng thời có gọi lệnh @JsonFactory.register để đăng ký Serialize và Deserialize đối tượng.
Lớp Category coding như sau:
from utils.JsonFactory import JsonFactory
@JsonFactory.register
class Category(object):
def __init__(self,cate_id=None,cate_name=None,products=None):
self.cate_id=cate_id
self.cate_name=cate_name
if products==None:
self.products=[]
else:
self.products=products
def add_product(self,p):
self.products.append(p)
def add_products(self,products):
self.products.extend(products)
def __str__(self):
return f"{self.cate_id}\t{self.cate_name}"
Lớp Category có các thuộc tính: cate_id, cate_name và danh sách sản phẩm (products).
Lớp Product cũng gọi lệnh @JsonFactory.register để đăng ký Serialize và Deserialize đối tượng.
Ngoài ra Tui viết thêm các hàm add_product() để thêm mới một Sản phẩm cho danh mục, và hàm add_products() để thêm nhiều sản phẩm cùng một lúc cho danh mục.
Cuối cùng là lớp Categories để lưu trữ danh sách Danh mục như sau:
from utils.JsonFactory import JsonFactory
@JsonFactory.register
class Categories(object):
def __init__(self,categories=None):
if categories==None:
self.categories=[]
else:
self.categories=categories
def add_cate(self,cate):
self.categories.append(cate)
def print_all_categories(self):
for cate in self.categories:
print("-" * 25)
print(cate)
print("-"*25)
for p in cate.products:
print(p)
Lớp Categories cũng gọi lệnh @JsonFactory.register để đăng ký Serialize và Deserialize đối tượng.
Lớp Categories Tui có bổ sung thêm hàm add_cate để thêm mới một Danh mục, và hàm print_all_categories() để xuất toàn bộ danh mục và từng sản phẩm của mỗi danh mục ra màn hình.
Ở đây, bạn có thể bổ sung thêm các mô hình lớp như: Employee, Customer, Order, OrderDetails, Supplier, ….
Bước 3: Thử nghiệm các lớp và thư viện
Trong thư mục “test”, hãy tạo một file “TestCategories.py” và giả lập một số dữ liệu như dưới đây:
from utils.JsonFactory import JsonFactory
from models.Categories import Categories
from models.Category import Category
from models.Product import Product
#Bước 1: Tạo một đối tượng database có kiểu Categories()
database=Categories()
#Bước 2: Tạo danh mục 1 và các sản phẩm liên quan
cate1=Category("c1","phone")
cate1.add_product(Product("p1","Samsung 1",100))
cate1.add_product(Product("p2","Samsung 2",400))
cate1.add_product(Product("p3","Samsung 3",200))
#Bước 3: Tạo danh mục 2 và các sản phẩm liên quan
cate2=Category("c2","computer")
cate2.add_product(Product("p4","DELL 1",2500))
cate2.add_product(Product("p5","DELL 2",3561))
cate2.add_product(Product("p6","DELL 3",4560))
#Bước 4: Tạo danh mục 3 và các sản phẩm liên quan
cate3=Category("c3","television")
cate3.add_product(Product("p7","Tele 1",6324))
cate3.add_product(Product("p8","Tele 2",1203))
cate3.add_product(Product("p9","Tele 3",2536))
#Bước 5: Đưa các danh mục vào database
database.add_cate(cate1)
database.add_cate(cate2)
database.add_cate(cate3)
#Bước 6: Xuất toàn bộ Danh sách dữ liệu mẫu:
database.print_all_categories()
Chạy các mã lệnh chương trình ở trên trong “TestCategories.py” ta có kết quả:

Quan sát kết quả ở trên ta thấy, chương trình đã xuất toàn bộ danh mục, và các sản phẩm của từng danh mục ra màn hình.
Bước tiếp theo là ta thử nghiệm các hàm Chuyển đổi Json, phục hồi object, serialize và deserialize.
Bước 3.1: Thử nghiệm hàm parse_json(). Ta bổ sung nối đuôi mã lệnh sau vào cuối file TestCategories.py:
#Bước 7: Parse đối tượng ra Json:
json_data = JsonFactory.parse_json(database)
print(json_data)
Chạy chương trình ta có kết quả:
{
"categories": [
{
"cate_id": "c1",
"cate_name": "phone",
"products": [
{
"product_id": "p1",
"product_name": "Samsung 1",
"unit_price": 100
},
{
"product_id": "p2",
"product_name": "Samsung 2",
"unit_price": 400
},
{
"product_id": "p3",
"product_name": "Samsung 3",
"unit_price": 200
}
]
},
{
"cate_id": "c2",
"cate_name": "computer",
"products": [
{
"product_id": "p4",
"product_name": "DELL 1",
"unit_price": 2500
},
{
"product_id": "p5",
"product_name": "DELL 2",
"unit_price": 3561
},
{
"product_id": "p6",
"product_name": "DELL 3",
"unit_price": 4560
}
]
},
{
"cate_id": "c3",
"cate_name": "television",
"products": [
{
"product_id": "p7",
"product_name": "Tele 1",
"unit_price": 6324
},
{
"product_id": "p8",
"product_name": "Tele 2",
"unit_price": 1203
},
{
"product_id": "p9",
"product_name": "Tele 3",
"unit_price": 2536
}
]
}
]
}
Bạn quan sát kết quả thì toàn bộ dữ liệu trong các đối tượng đã được chuyển thành Json, dĩ nhiên chuỗi Json này nó nằm trong bộ nhớ.
Bước 3.2: Thử nghiệm hàm restore_object(). Ta bổ sung nối đuôi mã lệnh sau vào cuối file TestCategories.py:
#Bước 8: Restore lại đối tượng từ Json:
restoreObject= JsonFactory.restore_object(json_data)
print("Dữ liệu sau khi Restore từ Json:")
restoreObject.print_all_categories()
Chạy chương trình ta có kết quả:

Ta thấy là đối tượng và các mối quan hệ giữa các đối tượng đã được phục hồi chính xác.
Bước 3.3: Thử nghiệm hàm serialize(). Ta bổ sung nối đuôi mã lệnh sau vào cuối file TestCategories.py:
#Bước 9: Gọi hàm serialize để chụp dữ liệu xuống ổ cứng với định dạng Json:
JsonFactory.serialize(database,"../assets/database.json")
Chạy mã lệnh ở trên, ta có kết quả là toàn bộ đối tượng được xuất ra tập tin database.json trong thư mục assets:

Bước 3.4: Thử nghiệm hàm deserialize(). Ta bổ sung nối đuôi mã lệnh sau vào cuối file TestCategories.py:
#Bước 10: Gọi hàm serialize để chụp dữ liệu xuống ổ cứng với định dạng Json:
myobj=JsonFactory.deserialize("../assets/database.json")
print("%"*20)
print("Dữ liệu sau khi deserialize từ file json:")
myobj.print_all_categories()
Khi chạy mã lệnh trên, chương trình sẽ nạp dữ liệu trong file “database.json” và phục hồi nó trở thành đối tượng và các mối quan hệ như trước khi nó serialize, kết quả:

Như vậy tới đây Tui đã hoàn tất hướng dẫn cách Serialize và Deserialize đối tượng – Json. Đây là bài toán tổng quát, bạn chỉ cần viết một lần duy nhất, các dự án khác với các đối tượng khác nhau bạn có thể tái sử dụng mà không cần viết lại.
Source code đầy đủ các bạn tải ở đây:
https://www.mediafire.com/file/kwmlihc62gswgf4/DemoComplexJsonAndOOP.rar/file
Chúc các bạn thành công!.