2.1 Модуль json

JSON (JavaScript Object Notation) — це легкий формат обміну даними, який легко читається і пишеться людиною, а також легко аналізується і генерується комп'ютером. JSON часто використовується для передачі даних між сервером і веб-додатком, а також для зберігання конфігурацій і налаштувань.

Модуль json в Python надає функції для серіалізації (перетворення об'єктів Python в строки JSON) і десеріалізації (перетворення строк JSON в об'єкти Python). Цей модуль вбудований в стандартну бібліотеку Python і активно використовується для роботи з JSON-даними.

Основні функції модуля json дуже нагадують такі у pickle і працюють аналогічно. А що ви хотіли — стандарт!

  • Робота зі строками:
    • json.dumps(obj) — Перетворює об'єкт Python в строку JSON.
    • json.loads(s) — Перетворює строку JSON в об'єкт Python.
  • Робота з файлами:
    • json.dump(obj, file) — Серіалізує об'єкт Python і записує його в текстовий файл.
    • json.load(file) — Десеріалізує об'єкт Python з текстового файлу, що містить дані у форматі JSON.

Давайте розберемо пару прикладів, щоб краще запам'ятати роботу цих функцій.

2.2 Серіалізація в строку

Серіалізація об'єктів Python в строки JSON

Для серіалізації об'єкта в строку потрібно просто передати його в функцію json.dumps().


import json

# Приклад об'єкта для серіалізації
data = {
    "name": "Alice",
    "age": 30,
    "is_student": False,
    "courses": ["Math", "Science"],
    "address": {
        "city": "New York",
        "zip_code": "10001"
    }
}
            
# Перетворення об'єкта Python в строку JSON
json_string = json.dumps(data, indent=4)
print("Серіалізовані дані (JSON):", json_string)
        

Десеріалізація строк JSON в об'єкти Python

Для отримання об'єкта зі строки потрібно просто передати JSON-строку, що містить опис об'єкта, в метод json.loads().


import json

# Приклад строки JSON для десеріалізації
json_string = '''
    {
        "name": "Alice",
        "age": 30,
        "is_student": false,
        "courses": ["Math", "Science"],
        "address": {
          "city": "New York",
          "zip_code": "10001"
        }
    }
    '''
            
# Перетворення строки JSON в об'єкт Python
data = json.loads(json_string)
print("Десеріалізовані дані (Python):", data)
        

2.3 Серіалізація в файл

Запис об'єктів Python в файл у форматі JSON

Для запису об'єкта в файл потрібно викликати метод json.dump(). При роботі з файлами важливо використовувати обробку виключень, щоб коректно обробляти можливі помилки. Ось приклад:


import json

# Приклад об'єкта для серіалізації
data = {
    "name": "Bob",
    "age": 25,
    "is_student": True,
    "courses": ["History", "Literature"],
    "address": {
        "city": "Los Angeles",
        "zip_code": "90001"
    }
}
            
# Запис об'єкта Python в файл JSON з обробкою виключень
try:
    with open('data.json', 'w') as file:
        json.dump(data, file, indent=4)
    print("Дані успішно записані в файл.")
except IOError:
    print("Помилка при записі в файл.")
except json.JSONEncodeError:
    print("Помилка при кодуванні JSON.")
            
        

Читання об'єктів Python з файлу у форматі JSON

Читання також дуже просте — просто передаємо файл в метод json.load(). Тут також важливо використовувати обробку виключень:


import json

# Читання об'єкта Python з файлу JSON з обробкою виключень
try:
    with open('data.json', 'r') as file:
        data = json.load(file)
    print("Десеріалізовані дані з файлу (Python):", data)
except IOError:
    print("Помилка при читанні файлу.")
except json.JSONDecodeError:
    print("Помилка при декодуванні JSON.")
        

2.4 Додаткові параметри функцій

У функцію, яка займається серіалізацією, можна передати додаткові параметри, які зроблять ваш JSON гарнішим:

  • skipkeys: Якщо True, то пропускає ключі, які не є строками, числами або None.
  • ensure_ascii: Якщо True, всі не-ASCII символи будуть екрановані за допомогою Unicode escape sequences.
  • indent: Якщо вказано число, відступи будуть додані для кращої читабельності.
  • sort_keys: Якщо True, ключі в JSON будуть відсортовані за алфавітом.

Приклад використання параметрів json.dumps():


import json

data = {"c": 3, "b": 2, "a": 1}
            
# Серіалізація з сортуванням ключів і відступами
json_string = json.dumps(data, indent=4, sort_keys=True)
print(json_string)
        

2.5 Користувацькі декодери і кодери

Модуль json дозволяє використовувати користувацькі функції для серіалізації і десеріалізації об'єктів.

Приклад користувацького кодера

Спочатку ми створюємо спеціальний клас-кодировщик, який всередині себе перевіряє, що якщо тип об'єкта == datetime, то повертає об'єкт як строку ISO-формату.


import json
from datetime import datetime
            
class CustomEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime):
            return obj.isoformat()
        return super().default(obj)
            
data = {
    "name": "Alice",
    "timestamp": datetime.now()
}
            
# Серіалізація з користувацьким кодером
json_string = json.dumps(data, cls=CustomEncoder, indent=4)
print(json_string)

Приклад користувацького декодера

Для зворотної операції нам теж потрібна функція, яка перетворює строку в дату. Наприклад, можна просто перевірити ім'я поля, і якщо воно називається timestamp, то перетворити строку в об'єкт datetime:


import json
from datetime import datetime
        
def custom_decoder(dct):
    if 'timestamp' in dct:
        dct['timestamp'] = datetime.fromisoformat(dct['timestamp'])
    return dct
        
json_string = '''
{
    "name": "Alice",
    "timestamp": "2023-05-15T14:30:00"
}
'''
        
# Десеріалізація з користувацьким декодером
data = json.loads(json_string, object_hook=custom_decoder)
print(data)