Hướng dẫn json dump python

Json (JavaScript Object Notation) là một chuẩn định dạng được dùng để lưu trữ và trao đổi dữ liệu giữa các tiến trình với nhau. Như tên gọi gợi ý phần nào, Json ban đầu là một phần của JavaScript, tuy nhiên hiện nay đã phát triển, có chuẩn riêng của mình, tồn tại độc lập không phụ thuộc JS hay bất kỳ ngôn ngữ lập trình nào cả.

Điểm đặc biệt của json là dữ liệu của nó có kiểu, bao gồm: object, array, string, number, boolean, null. Nội dung trong file json tồn tại theo cặp key: value. Trong đó, key luôn luôn là kiểu string, value thì có thể thuộc bất kỳ kiểu dữ liệu nào.

Ví dụ: people.json

{                                                                      
   "name": "Guido van Rossum",
   "age": 65,
   "degree": ["mathematics", "computer science"],
   "retired": true,
	"carrer": {
		"google":{
			"from": 1999,
			"to": 2013
		},
		"dropbox": {
			"from": 2013,
			"to": 2019
		}
}

}

Nếu theo đuổi sự nghiệp lập trình thì sớm hay muộn bạn cũng gặp định dạng json. Bất cứ khi nào xuất hiện nhu cầu lưu trữ (ổ cứng, database) hoặc trao đổi dữ liệu giữa các chương trình, thì json nên là một trong những từ khóa đầu tiên mà bạn nghĩ đến.

Lưu ý: Ngoài json, các định dạng file xml và yaml cũng được dùng để lưu trữ và trao đổi dữ liệu. Tuy nhiên, json ngày càng trở nên phổ biến hơn, vì những ưu điểm nó mang lại.

Xử lý Json với Python như thế nào?

Thao tác Serialize và Deserialize

Python dễ học nhưng cũng vô cùng mạnh mẽ, điều này được phản ảnh rõ nét trong cách nó hỗ trợ lập trình viên xử lý file json. Tận dụng lợi thế là một ngôn ngữ dynamic typing, cùng 2 cấu cấu trúc dữ liệu: dict, list, python sẽ làm bạn cảm thấy các thao tác với json thật tự nhiên và dễ dàng.

Tuy nhiên, trước khi đi sâu vào chi tiết, bạn cần biết sơ qua về cách chương trình máy tính (process) tương tác với file. Trong chương trình, bạn thao tác với các đối tượng (objects). Khi muốn lưu trữ hoặc truyền qua mạng, bạn cần chuyển các đối tượng trên về dạng mà máy tính có thể lưu trữ hoặc truyền đi được. Quá trình này được gọi là serialize. Quá trình ngược lại, khôi phục đối tượng từ file hoặc chuỗi bit nhận được qua mạng, được gọi là deserialize. Một cách đơn giản, khi muốn xử lý file json, bạn cần chuyển nội dung file json được lưu ở ổ cứng sang các đối tượng mà chương trình python hiểu được (deserialize). Khi muốn lưu các đối tượng dưới dạng json, bạn cần chuyển các đối tượng đó về dạng mà ổ cứng có thể lưu được (serialize).

Deserialize định dạng json

Từ phiên bản 2.6, Python đã bổ sung module json vào thư viện chuẩn. Do vậy, nếu phiên bản python của bạn cao hơn, để làm việc với json, bạn chỉ cần import module này vào. Nếu sử dụng phiên bản python thấp hơn, bạn có thể sử dụng pip để cài đặt gói này. Tuy nhiên, mình khuyến khích các bạn nên nâng cấp python lên phiên bản cao hơn, vì python 2.x đã không còn được hỗ trợ nữa.

import json

Trong quá trình deserialize, ta cần chuyển đổi từ json type sang python type. Bảng chuyển đổi tương ứng như sau:

Json Python
object dict
array list
string str
number(int) int
number(real) float 
true True
false False
null None 

Để deserialize một file json sang dạng object, ta dùng hàm load. Ví dụ với file people.json nêu ở trên

with open("people.json", "r") as fin:
    data = json.load(fin)
print(data)
>>> {'name': 'Guido van Rossum', 'age': 65, 'degree': ['mathematics', 'computer science'], 'retired': True, 'carrer': {'google': {'from': 1999, 'to': 2013}, 'dropbox': {'from': 2013, 'to': 2019}}}
print(type(data))
>>> 
print(type(data['age']))
>>> 
print(type('carrer'))
>>> 

Ta cũng có thể deserialize một json string, dùng hàm loads.

json_string = """
{
	"name": "Guido van Rossum",
	"age": 65,
	"degree": ["mathematics", "computer science"],
	"retired": true,
	"carrer": {
		"google":{
			"from": 1999,
			"to": 2013
		},
		"dropbox": {
			"from": 2013,
			"to": 2019
		}
	}
}
"""
data = json.loads(json_string)
print(data)
>>> {'name': 'Guido van Rossum', 'age': 65, 'degree': ['mathematics', 'computer science'], 'retired': True, 'carrer': {'google': {'from': 1999, 'to': 2013}, 'dropbox': {'from': 2013, 'to': 2019}}}
print(type(data))

Sau khi deserialize thành các object xong, bây giờ bạn có thể sử dụng chúng như bình thường.

print(len(data['degree']))
>>> 2
print(data['degree'][0])
>>> mathematics
print(data['age'] + 3)
>>> 68

Serialize python object sang json

Trong quá trình serialize, ta cần chuyển từ kiểu dữ liệu của python sang kiểu dữ liệu của json. Bảng chuyển đổi tương ứng như sau:

Python Json
dict object
list, tuple array
str string
int, long, float number
True true
False false
None null 

Để lưu một Python object lại dưới dạng file json, ta dùng hàm dump.

data = {'name': 'Guido van Rossum', 'age': 65, 'degree': ['mathematics', 'computer science'], 'retired': True, 'carrer': {'google': {'from': 1999, 'to': 2013}, 'dropbox': {'from': 2013, 'to': 2019}}}
with open("people.json", "w") as fout:
    json.dump(data, fout)

Hoặc nếu bạn chỉ cần chuyển một python object sang string json, dùng hàm dumps. Hàm dumps và dump cũng cung cho bạn thêm tham số indent để xâu kết quả nhìn đẹp mắt hơn.

data = {'name': 'Guido van Rossum', 'age': 65, 'degree': ['mathematics', 'computer science'], 'retired': True, 'carrer': {'google': {'from': 1999, 'to': 2013}, 'dropbox': {'from': 2013, 'to': 2019}}}
json_string = json.dumps(data)
print(json_string)
>>> {"name": "Guido van Rossum", "age": 65, "degree": ["mathematics", "computer science"], "retired": true, "carrer": {"google": {"from": 1999, "to": 2013}, "dropbox": {"from": 2013, "to": 2019}}}
print(type(json_string)
>>> 
json_string_2 = json.dumps(data, indent=4)
print(json_string_2)
>>> {
    "name": "Guido van Rossum",
    "age": 65,
    "degree": [
        "mathematics",
        "computer science"
    ],
    "retired": true,
    "carrer": {
        "google": {
            "from": 1999,
            "to": 2013
        },
        "dropbox": {
            "from": 2013,
            "to": 2019
        }
    }
}

Xử lý những object mà module json không hỗ trợ

Module json hỗ trợ hầu hết các kiểu dữ liệu được xây dựng sẵn (built-in types), cũng có nghĩa có một vài kiểu dữ liệu mà module này không hỗ trợ, complex là một trong số đó. Tương tự, module json cũng không thể tự serialize hay deserialize các kiểu dữ liệu do bạn tự định nghĩa (user-defined types), vì nó không có thông tin gì về các kiểu dữ liệu này. Nếu bạn xử lý như bình thường, sẽ có lỗi xảy ra

z = 3 + 2j
print(type(z))
>>> 
json.dumps(z)
>>> TypeError: Object of type complex is not JSON serializable

Với những kiểu dữ liệu này, bạn cần giúp đỡ python bằng cách cung cấp thêm cho nó các hàm trợ giúp: default cho serialize và object_hook cho deserialize.

Ví dụ: serialize kiểu dữ liệu complex

z = 3 + 2j
def encode_complex(z):
    if isinstance(z, complex):
        return (z.real, z.imag)
    else:
        raise TypeError("This type is not Json serializable")

a = json.dumps(z, default=encode_complex)
print(a)
>>> [3.0, 2.0]

Deserialize kiểu dữ liệu complex

def decode_complex(dct):
    return complex(dct['real'], dct['imag'])

a = """ {
"real": 3.0,
"imag": 2.0 }
"""

b = json.loads(a, object_hook=decode_complex)
print(b)
>>> (3 + 2j)
print(type(b))
>>> 

Serialize và deserialize các user-defined class

Với những class tự định nghĩa, bạn có thể tận dùng thuộc tính __dict__ để serialize và desialize dữ liệu. __dict__ trả ra một dictionary chứa các thuộc tính của đối tượng đó.

class People(object):

    def __init__(self, first_name: str, second_name: str):
        self.first_name = first_name
        self.second_name = second_name


people = People("Guido", "Russom")
print(people.__dict__)
>>> {'first_name': 'Guido', 'second_name': 'Russom'}

encode_data = json.dumps(people.__dict__)
print(encode_data)
>>> {"first_name": "Guido", "second_name": "Russom"}

decode_data = People(**json.loads(encode_data))
print(decode_data)
>>> <__main__.People object at 0x7f85a03e1990>
print(decode_data.first_name)
>>> Guido
print(decode_data.second_name)
>>> Russom

Ký tự ** trong decode_data = People(**json.loads(encode_data)) là cú pháp đặc biệt của python, để truyền một danh sách các keyword argument vào hàm.

Tổng kết

Như vậy, chúng ta đã cùng nhau đi qua tổng thể cách làm việc với định dạng json trong python. Ta có một vài kết luận rút gọn như sau:

  • Json là một chuẩn định dạng file được sử dụng phổ biến để lưu trữ và trao đổi thông tin
  • Serialize là quá trình chuyển một object trong chương trình về dạng mà máy tính có thể lưu trữ hoặc truyền đi được. Trong python, để serialize dữ liệu, ta dùng json.dump() hoặc json.dumps()
  • Deserialize là quá trình khôi phục lại các object từ file json hoặc chuỗi các bit nhận được từ mạng. Trong python, để deserialize dữ liệu, ta dùng json.load() hoặc json.loads()
  • Với những kiểu dữ liệu mà module json của python không hỗ trợ, ta cung cấp thêm các hàm trợ giúp cho python.

Hẹn gặp lại các bạn trong các bài viết sau!