%%
Напиши максимально простой пример использования этой библиотеки. Используй dump и load.
А так же дай деатльные пояснения.
Без использования marshmallow_dataclasses
Используй pre_load
для обработки данных (чтобы достать данные из вложенного словаря координат) если это возможно
Используй post_load
для десериализации в экземпляр класса
Обработай всю коллекцию за 1 проход
Используй этот набор данных для примера.
@dataclass
class City:
name: str
population: int
district: str
subject: str
lat: float
lon: float
email: str
cities_list = [
{ "coords": {
"lat": "52.65",
"lon": "90.08333"
},
"district": "Сибирский",
"name": "Абаза",
"population": 14816,
"subject": "Хакасия"
},
{ "coords": {
"lat": "53.71667",
"lon": "91.41667"
},
"district": "Сибирский",
"name": "Абакан",
"population": 187239,
"subject": "Хакасия"
}]
%%
[!info] Библиотека Marshmallow в Python — это инструмент, который помогает программистам превращать сложные данные (например, объекты классов Python) в более простые структуры, которые легко преобразовывать в формат JSON, а также делать обратное преобразование из JSON в объекты Python. Это особенно полезно при разработке веб-приложений, когда нужно отправлять и получать данные через интернет.
Чтобы понять, для чего нужна Marshmallow, представьте, что у вас есть приложение, где пользователи могут регистрироваться, входить в систему и обмениваться сообщениями. Каждый пользователь и сообщение в вашем приложении представлены сложными объектами в вашем коде. Однако, когда вы хотите отправить информацию о пользователе или сообщении через интернет другому пользователю или серверу, эти сложные объекты нужно преобразовать в формат, который легко читается и интерпретируется различными системами и языками программирования. Самым распространенным таким форматом является JSON.
Вот здесь на сцену выходит Marshmallow. Эта библиотека позволяет вам легко:
-
Сериализация: преобразование объектов Python (например, моделей данных вашего приложения) в словари Python, которые затем можно легко превратить в строку JSON. Это полезно, когда вы хотите отправить данные из вашего приложения на внешний сервер или клиент.
-
Десериализация: обратный процесс, при котором данные в формате JSON преобразуются обратно в объекты Python. Это полезно, когда ваше приложение получает данные в формате JSON, например, от веб-формы или внешнего API, и вам нужно использовать эти данные в вашем приложении как объекты Python.
Кроме того, Marshmallow помогает валидировать данные, то есть проверять их на соответствие определенным правилам или ограничениям. Например, если вы ожидаете, что пользователь введет свой возраст как число, Marshmallow может проверить, что полученное значение действительно является числом, и выдать ошибку, если это не так.
В общем, Marshmallow упрощает работу с данными между вашим Python-приложением и внешним миром, делая процессы сериализации, десериализации и валидации данных более простыми и безопасными.
В библиотеке Marshmallow сущности "схема" (Schema) и "поле" (Field) играют ключевую роль в процессе сериализации и десериализации данных. Понимание этих сущностей важно для эффективного использования библиотеки. Давайте рассмотрим каждую из них подробнее.
Схема в Marshmallow — это класс, который определяет, как данные должны быть сериализованы (преобразованы в простые типы данных, например, в словарь или строку JSON) или десериализованы (преобразованы обратно в сложные типы данных, например, в объекты Python). Схема работает как карта или шаблон, указывая, какие поля данных присутствуют, как они должны обрабатываться и какие дополнительные проверки или преобразования могут потребоваться при этом обработке.
Основная роль схемы — упростить процесс преобразования данных, обеспечив при этом их валидацию и соблюдение структуры. Схемы позволяют определить, какие поля включать в сериализованные данные, какие исключать, как обрабатывать отсутствующие или дополнительные поля и как преобразовывать типы данных между Python и форматом, пригодным для обмена данными (например, JSON).
Поля в Marshmallow — это компоненты схемы, каждый из которых соответствует определенному элементу данных. Поле определяет тип данных (например, строка, число, дата), который оно представляет, и содержит логику для его сериализации и десериализации и валдации. Поля могут также содержать дополнительные параметры для валидации (например, обязательное поле, ограничения длины для строк) и преобразования данных (например, преобразование строки в дату).
Каждое поле в схеме Marshmallow представляет собой инстанс класса, производного от базового класса Field
. Библиотека предоставляет множество готовых классов полей для различных типов данных, таких как String
для строк, Integer
для целых чисел, Float
для чисел с плавающей точкой, DateTime
для даты и времени и многих других. Разработчики могут также создавать свои собственные классы полей для обработки специфических типов данных или выполнения особых задач сериализации/десериализации.
Ключевые аспекты работы с полями:
- Сериализация: поля преобразуют данные из сложных объектов Python в формат, подходящий для JSON (или других форматов), например, преобразование объекта даты в строку.
- Десериализация: поля преобразуют данные из простого формата (например, из JSON) обратно в сложные типы данных Python, например, строку в объект даты.
- Валидация: поля могут проверять данные на соответствие определенным условиям или ограничениям, например, что число не отрицательное или что строка соответствует определенному шаблону.
Вместе схема и поля позволяют точно и гибко управлять процессом сериализации и десериализации данных, обеспечивая при этом их корректность и соответствие заданным требованиям. Это облегчает обмен данными между различными частями приложения или между разными системами, делая код более чистым, понятным и безопасным.
Поля могут быть настроены на выполнение различных задач помимо основных преобразований типов и валидации. Например, можно задать параметры по умолчанию для полей, которые будут использоваться, если соответствующие данные отсутствуют при десериализации. Также поля могут быть настроены на пропуск значений, если они отсутствуют при сериализации, что может быть полезно для управления представлением данных при отправке клиенту.
В контексте веб-разработки и API, схемы и поля Marshmallow особенно полезны для следующих задач:
- Подготовка данных для ответов API: Сериализация объектов данных в формат JSON для отправки клиентам через HTTP ответы.
- Обработка и проверка входящих данных: Десериализация и валидация данных, полученных от клиентов, например, в JSON формате через HTTP запросы, для последующего использования в приложении.
- Преобразование между различными представлениями данных: Например, преобразование между сложными объектами доменной модели и более простыми структурами данных, подходящими для хранения в базе данных или кеширования.
Один из ключевых аспектов использования схем и полей — возможность валидации данных. Валидация позволяет убедиться, что данные, получаемые от пользователей или других внешних источников, соответствуют ожидаемым требованиям и ограничениям, прежде чем они будут использованы в приложении. Это важный элемент безопасности и надежности приложений, так как предотвращает использование некорректных или злонамеренных данных.
Схемы и поля в Marshmallow формируют мощный инструментарий для работы с данными в приложениях на Python. Они обеспечивают гибкость и контроль над процессом сериализации и десериализации данных, позволяя разработчикам фокусироваться на логике приложения, не беспокоясь о деталях реализации обмена данными и обработки форматов. Валидация данных на уровне схемы и полей способствует созданию более безопасных и надежных приложений, защищая от некорректных входных данных и обеспечивая корректность обработки данных на всех этапах работы приложения.
Давайте использовать библиотеку Marshmallow для того, чтобы преобразовать данные из списка словарей cities_list
в объекты класса City
, а также наоборот. Прежде всего, определим класс City
, который будет представлять данные о городе, и затем создадим схему Marshmallow для сериализации и десериализации этих данных.
from dataclasses import dataclass
@dataclass
class City:
name: str
population: int
district: str
subject: str
lat: float
lon: float
email: str # Добавим поле email, но оно не будет заполняться из нашего списка, так как там его нет.
cities_list = [
{ "coords": {
"lat": "52.65",
"lon": "90.08333"
},
"district": "Сибирский",
"name": "Абаза",
"population": 14816,
"subject": "Хакасия"
},
{ "coords": {
"lat": "53.71667",
"lon": "91.41667"
},
"district": "Сибирский",
"name": "Абакан",
"population": 187239,
"subject": "Хакасия"
}]
Следующим шагом будет создание схемы Marshmallow. Схема определяет, как поля объекта City
соотносятся с данными в словаре (и наоборот).
from marshmallow import Schema, fields, post_load
class CitySchema(Schema):
name = fields.Str()
population = fields.Int()
district = fields.Str()
subject = fields.Str()
lat = fields.Float()
lon = fields.Float()
email = fields.Email(missing="[email protected]") # Устанавливаем значение по умолчанию для email
# Функция post_load не используется по вашей просьбе.
Теперь, когда у нас есть класс данных и схема, мы можем сериализовать объекты City
в словари и десериализовать данные из списка cities_list
в объекты City
.
Преобразуем словари из списка cities_list
в объекты City
. Поскольку в исходных данных координаты находятся во вложенном словаре coords
, нам нужно немного их преобразовать перед десериализацией.
# Создаём экземпляр схемы
schema = CitySchema()
# Пример десериализации для первого города в списке
example_city_dict = cities_list[0]
example_city_dict["lat"] = example_city_dict["coords"]["lat"]
example_city_dict["lon"] = example_city_dict["coords"]["lon"]
# Удаляем вложенный словарь 'coords', так как он больше не нужен
del example_city_dict["coords"]
# Десериализация словаря в объект City
city_object = schema.load(example_city_dict)
print(city_object)
Теперь преобразуем объект City
обратно в словарь.
# Сериализация объекта City в словарь
city_dict = schema.dump(city_object)
print(city_dict)
- Сериализация (преобразование объекта в словарь) полезна, когда нужно сохранить объект в базе данных или отправить его через API.
- Десериализация (преобразование словаря в объект) удобна для создания объектов на основе данных, полученных из внешних источников, например, из запросов к API или из файлов JSON.
В этом примере мы использовали CitySchema
для описания, как данные должны быть преобразованы из словаря в объект City
и обратно, а также установили значение по умолчанию для поля email
, которое отсутствует в исходных данных.
Давайте разберём несколько продвинутых возможностей библиотеки Marshmallow, которые делают её ещё более мощным инструментом для работы с сериализацией и десериализацией данных, а также для валидации.
Декораторы @pre_load
и @post_load
используются для выполнения кода до или после десериализации данных соответственно. Это позволяет разработчикам добавлять дополнительную логику обработки данных, которая не ограничивается стандартным процессом преобразования и валидации, предоставляемым полями схемы.
-
@pre_load
: Этот декоратор применяется к методам схемы, которые должны быть вызваны перед началом процесса десериализации. Это может быть полезно для предварительной обработки входных данных, например, для нормализации данных или для преобразования форматов данных, не поддерживаемых стандартными полями. -
@post_load
: Декоратор@post_load
используется для методов, которые вызываются после того, как данные были десериализованы в объект. Это может быть полезно для пост-обработки объекта, например, для установки дополнительных атрибутов, которые вычисляются на основе других атрибутов объекта, или для преобразования промежуточного объекта в окончательный объект вашей модели.
Marshmallow позволяет не только валидировать отдельные поля, но и обеспечивает возможность валидации всей коллекции (например, списка или словаря) целиком. Это означает, что можно проверить данные на более высоком уровне, например, убедиться, что список элементов содержит элементы уникальные по определённому признаку или что комбинация значений в словаре удовлетворяет определённым условиям. Такая возможность особенно полезна, когда требуется выполнить комплексные проверки, которые не могут быть связаны с одним конкретным полем.
-
Вложенные схемы: Marshmallow позволяет определять вложенные схемы, что особенно полезно при работе со сложными структурами данных, содержащими вложенные объекты. Это позволяет точно описать, как должны быть сериализованы и десериализованы вложенные данные, обеспечивая при этом их корректность и соответствие структуре.
-
Поля со множественными значениями: С помощью специальных полей, таких как
List
илиDict
, можно описывать поля, содержащие множество значений (например, списки или словари). Это позволяет удобно работать с коллекциями данных, сериализовывая и десериализовывая их содержимое. -
Методы
validate
: Marshmallow предоставляет возможность валидации данных на уровне схемы с помощью вызова методаvalidate
. Это позволяет проверить данные перед их обработкой и, в случае обнаружения ошибок, получить детальную информацию о них. -
Кастомизация сообщений об ошибках: В Marshmallow можно не только валидировать данные, но и настраивать сообщения об ошибках валидации для каждого поля. Это позволяет предоставлять более понятные и детализированные сообщения пользователям или разработчикам, что упрощает процесс отладки и повышает удобство использования API или приложения в целом.
-
Условное включение полей: Существует возможность динамически включать или исключать поля из сериализации в зависимости от определённых условий. Это может быть полезно, например, для адаптации ответов API в соответствии с правами доступа пользователя или для оптимизации передаваемых данных в зависимости от контекста запроса.
-
Автоматическое создание документации: Используя схемы Marshmallow, можно автоматически генерировать документацию для API. Поскольку схемы точно описывают структуру данных, они могут быть использованы инструментами для генерации документации, что упрощает поддержку актуальной и точной документации для внешних разработчиков.
-
Интеграция с ORМ библиотеками: Marshmallow может быть интегрирован с различными ORМ библиотеками (например, SQLAlchemy), что позволяет упростить преобразование данных между форматом, пригодным для базы данных, и форматом, используемым в приложении или API. Это значительно сокращает количество шаблонного кода, необходимого для работы с данными.
-
Кастомные поля и валидаторы: Для обработки специфических требований к данным или для валидации, которая не поддерживается стандартными полями и валидаторами, Marshmallow позволяет создавать кастомные поля и валидаторы. Это предоставляет практически неограниченные возможности для адаптации библиотеки под конкретные нужды проекта.
-
Оптимизация производительности с помощью кэширования: Для повышения производительности сериализации и десериализации Marshmallow поддерживает кэширование определений схем и полей. Это позволяет сократить время обработки данных, особенно при работе с большими объёмами данных или сложными структурами.
В целом, Marshmallow предлагает богатый набор инструментов для работы с сериализацией и десериализацией данных, а также для валидации. Благодаря своей гибкости и расширяемости, Marshmallow может быть адаптирован под практически любые требования к работе с данными, делая процесс разработки более эффективным и безопасным.
Для реализации этой задачи мы сначала определим класс City
, который будет представлять данные о городе. Затем создадим схему Marshmallow для обработки этих данных, включая декораторы @pre_load
для предварительной обработки вложенных координат и @post_load
для создания экземпляров City
из десериализованных данных. Наконец, мы обработаем весь список городов за один проход, используя эти настройки.
from dataclasses import dataclass
@dataclass
class City:
name: str
population: int
district: str
subject: str
lat: float
lon: float
email: str # Это поле будет игнорироваться при десериализации, так как в данных его нет.
from dataclasses import dataclass
from marshmallow import Schema, fields, pre_load, post_load
@dataclass
class City:
name: str
population: int
district: str
subject: str
lat: float
lon: float
email: str
cities_list = [
{"coords": {
"lat": "52.65",
"lon": "90.08333"
},
"district": "Сибирский",
"name": "Абаза",
"population": 14816,
"subject": "Хакасия"
},
{"coords": {
"lat": "53.71667",
"lon": "91.41667"
},
"district": "Сибирский",
"name": "Абакан",
"population": 187239,
"subject": "Хакасия"
}]
class CitySchema(Schema):
name = fields.Str()
population = fields.Int()
district = fields.Str()
subject = fields.Str()
lat = fields.Float()
lon = fields.Float()
email = fields.Str(load_default='[email protected]') # Устанавливаем значение по умолчанию для email
@pre_load()
def unwrap_coords(self, data, **kwargs):
# Этот метод будет вызван до десериализации каждого элемента списка.
# Он изменяет структуру данных, извлекая координаты из вложенного словаря.
# Делаем копию словаря, чтобы не изменять оригинальные данные
data = data.copy()
data.update({
'lat': data['coords']['lat'],
'lon': data['coords']['lon']
})
del data['coords'] # Удаляем исходный вложенный словарь координат
return data
@post_load
def make_city(self, data, **kwargs):
# Этот метод создает экземпляр City из десериализованных данных.
return City(**data)
schema_many = CitySchema(many=True)
schema = CitySchema()
# Поштучно и множественно
cities = schema_many.load(cities_list)
print(cities)
city = schema.load(cities_list[0])
print(city)
# Сериализация - пробуем сделать dump
city2 = schema.dump(city)
print(city2)
Этот код демонстрирует использование библиотеки Marshmallow для сериализации и десериализации данных, а также некоторые продвинутые возможности, такие как обработка вложенных структур данных и создание экземпляров классов.
-
Определение класса данных
City
: Здесь используется декоратор@dataclass
из модуляdataclasses
, чтобы определить простой классCity
с атрибутами, соответствующими данным о городе. Это включает в себя название, население, район, субъект, координаты и электронную почту. -
Подготовка данных
cities_list
: Создается список словарей, каждый из которых содержит информацию о городе, включая координаты во вложенном словаре. -
Создание схемы
CitySchema
с помощью Marshmallow:- Определение полей: Для каждого атрибута класса
City
определяется соответствующее поле Marshmallow. Например,name = fields.Str()
указывает, чтоname
является строкой. Для поляemail
устанавливается значение по умолчанию. - Метод
@pre_load
: Используется для предварительной обработки каждого элемента списка перед его десериализацией. В этом методе координаты извлекаются из вложенного словаряcoords
и добавляются непосредственно в основной словарь, после чегоcoords
удаляется. - Метод
@post_load
: После десериализации данных в словарь, этот метод используется для создания экземпляра классаCity
, используя десериализованные данные.
- Определение полей: Для каждого атрибута класса
-
Десериализация данных:
- С использованием
CitySchema(many=True)
, обрабатывается список словарейcities_list
, преобразуя его в список экземпляров классаCity
. Это демонстрирует возможность работы со множеством элементов за один проход. - Также показана десериализация отдельного элемента списка для создания одного экземпляра
City
.
- С использованием
-
Сериализация данных: Используя метод
dump
, экземплярCity
сериализуется обратно в словарь. Это позволяет преобразовать объекты Python в формат, подходящий для передачи данных или сохранения.
- Предварительная и постобработка данных: Демонстрируется, как можно модифицировать данные перед и после процесса десериализации, что особенно полезно при работе со сложными структурами данных.
- Универсальность обработки: Показывается, как одна и та же схема может быть использована как для обработки отдельных элементов, так и для работы с целым списком данных.
- Сериализация и десериализация: Пример иллюстрирует, как данные могут быть преобразованы из словарей в объекты и обратно, что является ключевой особенностью Marshmallow.
В итоге, код демонстрирует, как Marshmallow упрощает обработку и валидацию данных при разработке приложений, особенно когда необходимо работать с вложенными структурами или автоматически создавать объекты на основе данных.
Поля в Marshmallow являются основными строительными блоками схем, и они используются для определения того, как данные должны быть сериализованы (преобразованы в простой формат, например, в JSON) или десериализованы (преобразованы обратно в сложные типы данных, например, в объекты Python). В скобках у каждого поля вы можете указать различные параметры и валидаторы, которые определяют, как должно обрабатываться содержимое этого поля. Давайте рассмотрим наиболее распространенные из них.
required
: Определяет, является ли поле обязательным для заполнения. Если поле отмечено как обязательное, но отсутствует во входных данных, Marshmallow сгенерирует ошибку.missing
: Задает значение по умолчанию для поля, если оно отсутствует во входных данных при десериализации.default
: Устанавливает значение по умолчанию для поля при сериализации, если значение атрибута объекта отсутствует.allow_none
: Указывает, может ли поле принимать значениеNone
.validate
: Принимает функцию валидации или список функций, которые вызываются для проверки значения поля. Если значение не проходит валидацию, будет сгенерирована ошибка.error_messages
: Словарь, который позволяет переопределить стандартные сообщения об ошибках для различных типов ошибок валидации.
Разные типы полей могут поддерживать дополнительные параметры, специфичные для их типа. Например:
String
:length
: Может использоваться для указания минимальной и/или максимальной длины строки.
Number
(включаетInteger
,Float
):strict
: Указывает, должно ли поле строго соответствовать типу (например, только целым числам дляInteger
).round
(дляFloat
): Определяет количество знаков после запятой, до которого следует округлить число при сериализации.
DateTime
:format
: Строка формата, определяющая, как дата и время должны быть сериализованы или десериализованы.
Валидаторы — это функции, которые используются для проверки данных. Marshmallow предоставляет несколько встроенных валидаторов, таких как проверка на минимальное/максимальное значение, соответствие регулярному выражению и т.д. Вы также можете определить свои собственные функции валидации. Валидаторы применяются к данным во время десериализации и могут генерировать ошибки, если данные не соответствуют заданным критериям.
Параметры полей позволяют вам тонко настроить процесс сериализации и десериализации, обеспечивать корректность данных и генерировать понятные сообщения об ошибках для конечных пользователей или разработчиков, работающих с вашим API или приложением. Благодаря этим возможностям, Marshmallow облегчает создание надежных и удобных в использовании интерфейсов обмена данными, обеспечивая при этом высокий уровень контроля над процессом обработки данных.
Ключевые моменты, которые следует учитывать при работе с параметрами полей в Marshmallow:
- Гибкость настройки: Параметры предоставляют возможность детально настроить обработку каждого поля в вашей схеме, начиная от базовой валидации и заканчивая сложными преобразованиями данных.
- Улучшение взаимодействия с пользователем: Правильное использование параметров, таких как
error_messages
иvalidate
, помогает предоставлять понятные сообщения об ошибках, что улучшает опыт работы с вашим приложением или API. - Валидация данных: Параметры валидации позволяют обеспечить, что данные не только корректно сериализуются и десериализуются, но и соответствуют определенным бизнес-правилам или требованиям безопасности.
- Адаптация под специфические требования: Благодаря возможности создавать кастомные валидаторы и использовать специфические параметры для разных типов полей, Marshmallow позволяет адаптировать процесс работы с данными под почти любые специфические требования вашего приложения или сервиса.
Важно помнить, что правильное использование параметров полей не только повышает качество ваших данных, но и может существенно упростить логику обработки данных в вашем приложении, делая код более чистым и понятным.
В итоге, Marshmallow предоставляет мощный и гибкий инструментарий для работы с сериализацией и десериализацией данных, а также для их валидации. Понимание и правильное использование параметров полей позволит вам максимально эффективно использовать этот инструментарий для решения задач, связанных с обработкой и обменом данными.
from dataclasses import dataclass, field
from marshmallow import Schema, fields, pre_load, post_load
@dataclass
class City:
name: str
population: int
district: str
subject: str
email: str
coords: dict = field(default_factory=dict)
cities_list = [
{"coords": {
"lat": "52.65",
"lon": "90.08333"
},
"district": "Сибирский",
"name": "Абаза",
"population": 14816,
"subject": "Хакасия"
},
{"coords": {
"lat": "53.71667",
"lon": "91.41667"
},
"district": "Сибирский",
"name": "Абакан",
"population": 187239,
"subject": "Хакасия"
}]
class CoordsSchema(Schema):
lat = fields.Float()
lon = fields.Float()
class CitySchema(Schema):
name = fields.Str()
population = fields.Int()
district = fields.Str()
subject = fields.Str()
coords = fields.Nested(CoordsSchema)
email = fields.Str(load_default='[email protected]') # Устанавливаем значение по умолчанию для email
@post_load
def make_city(self, data, **kwargs):
# Этот метод создает экземпляр City из десериализованных данных.
# return City(population=data['population'], district=data['district'], # subject=data['subject'], email=data['email'], coords=data['coords'], name=data['name'])
return City(**data)
schema_many = CitySchema(many=True)
schema = CitySchema()
# Поштучно и множественно
cities = schema_many.load(cities_list)
print(cities)
city = schema.load(cities_list[0])
print(city)
# Сериализация - пробуем сделать dump
city2 = schema.dump(city)
print(city2)
В этом коде реализуется процесс сериализации и десериализации данных о городах с использованием библиотеки Marshmallow и Python Dataclasses. Вот что происходит в каждом из его основных компонентов:
- Класс
City
создан как dataclass, что упрощает определение классов, автоматически добавляя специальные методы, включая__init__
,__repr__
,__eq__
, и другие. - Этот класс имеет атрибуты для хранения информации о городе: имя, население, район, субъект, электронная почта и координаты. Координаты представлены словарем, созданным с использованием
default_factory
вfield
, что гарантирует, что по умолчаниюcoords
будет пустым словарем, если при создании экземпляра классаCity
он не указан.
- Представлен список
cities_list
, содержащий информацию о двух городах, включая их координаты, население, район и субъект. Данные о координатах находятся во вложенном словаре.
- Класс
CoordsSchema
определяет схему для вложенного словаря координат, используя поляfields.Float()
для широты (lat
) и долготы (lon
).
- Класс
CitySchema
определяет, как данные о городах должны быть десериализованы в экземпляры классаCity
и сериализованы обратно в словари. - Использует
fields.Nested(CoordsSchema)
для обработки вложенного словаря координат, указывая, что эти данные должны быть обработаны согласно схемеCoordsSchema
. - Поле
email
использует параметрload_default
, который указывает значение по умолчанию для этого поля при десериализации, если оно отсутствует в исходных данных. - Метод
@post_load
используется для создания и возврата экземпляраCity
после того, как данные были успешно десериализованы.**data
позволяет передать десериализованные данные напрямую в конструкторCity
, автоматически распаковывая словарь в аргументы.
- Десериализация:
schema_many.load(cities_list)
преобразует список словарей с данными о городах в список экземпляровCity
, используя определенную выше схему.schema.load(cities_list[0])
делает то же самое, но только для первого города в списке. - Сериализация:
schema.dump(city)
преобразует экземплярCity
обратно в словарь, используя ту же схему.
В итоге, этот код демонстрирует мощные возможности Marshmallow для обработки сложных структур данных, включая вложенные словари и автоматическое создание объектов на основе десериализованных данных.
marshmallow_dataclass
— это библиотека, которая сочетает в себе возможности двух мощных инструментов Python: dataclasses
и Marshmallow
. Это делается для упрощения и автоматизации процесса сериализации и десериализации данных, а также для обеспечения валидации данных при их преобразовании из/в Python объекты. Вот как это работает и для чего это нужно:
- Автоматическое создание схем Marshmallow: Одна из основных задач при использовании Marshmallow — создание схем для сериализации и десериализации объектов. Это может быть довольно много шаблонного кода, если у вас много классов данных.
marshmallow_dataclass
автоматически генерирует эти схемы на основе классов данных (dataclasses
), что сокращает количество кода и уменьшает вероятность ошибок. - Типизация и валидация: Python 3.6 и более поздние версии поддерживают аннотации типов, которые позволяют разработчикам указывать, какого типа должны быть атрибуты объектов.
marshmallow_dataclass
использует эту информацию для автоматической валидации данных при их сериализации/десериализации, гарантируя, что данные соответствуют ожидаемым типам и ограничениям.
Когда вы определяете класс данных с помощью dataclasses
, вы можете указать типы атрибутов и, используя marshmallow_dataclass
, автоматически генерировать схему Marshmallow для этого класса. Эта схема затем может быть использована для:
- Сериализации объектов в JSON (или другие форматы): Это полезно для создания API, где вам нужно отправлять данные в формате, понятном клиентам (например, веб-браузерам).
- Десериализации данных из внешних источников: Например, при получении данных в формате JSON от клиента, вы можете преобразовать их обратно в объекты Python для дальнейшей обработки.
- Валидации данных: В процессе сериализации и десериализации данные автоматически проверяются на соответствие указанным типам и ограничениям. Это помогает предотвратить ошибки из-за некорректных данных.
Использование marshmallow_dataclass
особенно полезно в ситуациях, когда вы работаете с большим количеством классов данных в вашем приложении и хотите эффективно управлять процессом их сериализации/десериализации и валидации. Это обычно встречается в веб-разработке, при создании REST API, а также в любых приложениях, где требуется строгий контроль типов и форматов данных.
Сокращая количество шаблонного кода и автоматизируя создание схем, marshmallow_dataclass
повышает эффективность разработки и обеспечивает более высокую надежность кода за счет строгой типизации и валидации данных.
from dataclasses import dataclass, field
from marshmallow import Schema, fields, pre_load, post_load
import marshmallow_dataclass
@dataclass
class City:
name: str
population: int
district: str
subject: str
coords: dict = field(default_factory=dict)
cities_list = [
{"coords": {
"lat": "52.65",
"lon": "90.08333"
},
"district": "Сибирский",
"name": "Абаза",
"population": 14816,
"subject": "Хакасия"
},
{"coords": {
"lat": "53.71667",
"lon": "91.41667"
},
"district": "Сибирский",
"name": "Абакан",
"population": 187239,
"subject": "Хакасия"
}]
# Создание схемы на основе датакласса
CitySchema = marshmallow_dataclass.class_schema(City)
# Создание экземпляра схемы
city_schema = CitySchema(many=True)
# Десериализация данных
cities = city_schema.load(cities_list)
print(cities)
В этом примере кода демонстрируется процесс создания класса данных для города (City
), сериализации и десериализации списка таких городов с использованием библиотеки marshmallow_dataclass
. Всё это выполняется без явного определения схемы Marshmallow, что упрощает и ускоряет процесс разработки.
-
Определение класса
City
: С помощью декоратора@dataclass
создается классCity
, который содержит информацию о городе, включая его название, население, район, субъект и координаты. Координаты представлены в виде словаря, который инициализируется как пустой по умолчанию с помощьюfield(default_factory=dict)
. -
Подготовка списка городов: Создается список словарей
cities_list
, каждый из которых содержит данные о конкретном городе, включая вложенный словарь с координатами (lat
иlon
). -
Использование
marshmallow_dataclass
для автоматического создания схемы: С помощью функцииmarshmallow_dataclass.class_schema
, автоматически генерируется схема Marshmallow для классаCity
, основываясь на его определении. Это позволяет избежать ручного определения полей схемы, что обычно требуется при работе с Marshmallow напрямую. -
Сериализация и десериализация данных: Создается экземпляр схемы
CitySchema
с параметромmany=True
, который указывает, что схема предназначена для обработки списка объектов. Этот экземпляр затем используется для десериализации списка словарейcities_list
в список экземпляров классаCity
. Результат показывается на экране.
В Marshmallow класс Meta
внутри схемы используется для настройки поведения самой схемы. Он позволяет задавать различные параметры, влияющие на сериализацию и десериализацию данных, валидацию, а также предоставляет возможность исключения или добавления определенных полей при сериализации.
Для реализации необязательности поля email
и задания его значения по умолчанию через класс Meta
в Marshmallow, можно использовать параметр load_default
в определении поля схемы или указать это поведение непосредственно для класса данных, если используется автоматическая генерация схемы через marshmallow_dataclass
.
marshmallow_dataclass
упрощает работу с датаклассами и Marshmallow, автоматически генерируя схемы на основе аннотаций типов и дополнительных параметров, передаваемых непосредственно в декораторы или функции поля (field
). Это позволяет интегрировать настройки Marshmallow напрямую в определение датакласса, не требуя отдельного определения схемы.
Чтобы сделать поле email
необязательным и задать значение по умолчанию при использовании marshmallow_dataclass
, можно воспользоваться функцией field
из модуля dataclasses
, передав ей параметр metadata
, в котором указывается словарь с настройками для Marshmallow. В этом словаре можно задать load_default
, чтобы указать значение по умолчанию для поля email
, если оно отсутствует в исходных данных.
-
Использование класса Meta в Marshmallow — это классический подход, при котором настройки схемы задаются внутри определения самой схемы. Это обеспечивает гибкость и мощные возможности для настройки процесса сериализации/десериализации, но может потребовать дополнительного кода для определения схемы, отдельного от датакласса.
-
Метаинформация в полях с использованием
marshmallow_dataclass
позволяет интегрировать настройки сериализации и валидации непосредственно в определение датакласса, сокращая количество шаблонного кода и упрощая процесс создания и поддержки моделей данных. Этот подход идеально подходит для ситуаций, когда логика приложения тесно связана с структурой данных, и требуется автоматическая валидация и преобразование типов данных.
Оба подхода предлагают эффективные средства для работы с сериализацией и десериализацией данных в Python, выбор между ними зависит от конкретных требований проекта и предпочтений разработчика.
from dataclasses import dataclass, field
from marshmallow import Schema, fields, pre_load, post_load
import marshmallow_dataclass
@dataclass
class City:
name: str
district: str
subject: str
population: int
email: str = field(default="", metadata={"load_default": "",
"load_only": True})
coords: dict = field(default_factory=dict)
cities_list = [
{"coords": {
"lat": "52.65",
"lon": "90.08333"
},
"district": "Сибирский",
"name": "Абаза",
"population": -14816,
"subject": "Хакасия"
},
{"coords": {
"lat": "53.71667",
"lon": "91.41667"
},
"district": "Сибирский",
"name": "Абакан",
"population": 187239,
"subject": "Хакасия"
}]
# Создание схемы на основе датакласса
CitySchema = marshmallow_dataclass.class_schema(City)
# Создание экземпляра схемы
city_schema = CitySchema(many=True)
# Десериализация данных
cities = city_schema.load(cities_list)
print(cities)
# Сериализация данных
data = city_schema.dump(cities)
print(data)
Этот пример кода демонстрирует использование библиотеки marshmallow_dataclass
для автоматического создания схемы Marshmallow из датакласса Python для сериализации и десериализации данных. Давайте разберём его по частям.
Класс City
определён с использованием декоратора @dataclass
из модуля dataclasses
. Этот класс представляет собой модель данных города с полями: название (name
), район (district
), субъект (subject
), население (population
), электронная почта (email
) и координаты (coords
).
Особенность поля email
заключается в использовании параметра default
для задания пустой строки как значения по умолчанию и в метаданных (metadata
), которые содержат дополнительные настройки для Marshmallow:
"load_default": ""
указывает, что при десериализации данных, если полеemail
отсутствует, должно использоваться пустое строковое значение."load_only": True
означает, что это поле предназначено только для десериализации (загрузки данных), но не должно учитываться при сериализации (выгрузке данных).
Поле coords
инициализируется с помощью default_factory=dict
, что обеспечивает создание пустого словаря для координат, если при создании экземпляра City
координаты не указаны.
Список cities_list
содержит словари с данными о двух городах. Эти данные включают вложенный словарь coords
с широтой (lat
) и долготой (lon
).
marshmallow_dataclass.class_schema(City)
автоматически генерирует схему Marshmallow на основе датакласса City
. Эта схема используется для десериализации списка словарей cities_list
в список экземпляров City
, а также для последующей сериализации объектов City
обратно в формат словаря.
- При десериализации (
city_schema.load(cities_list)
) данные из списка словарей преобразуются в список объектовCity
. - При сериализации (
city_schema.dump(cities)
) объектыCity
преобразуются обратно в список словарей.
Эти операции показывают, как данные могут быть загружены из внешнего источника, обработаны и затем представлены в нужном формате.
Помимо указанных параметров (load_default
, load_only
), через метаданные можно передать и другие настройки для полей, используемых в Marshmallow, включая валидаторы (validate
) и параметры валидаторов. Например, можно указать функцию валидации, которая проверит, что население города (population
) является положительным числом, или задать регулярное выражение для проверки формата электронной почты.
Эти метаданные делают определение класса данных более мощным и гибким инструментом для управления процессом сериализации/десериализации и валидации данных, обеспечивая тем самым точность и надёжность обработки данных в приложениях.
from dataclasses import dataclass, field
from marshmallow import Schema, fields, pre_load, post_load
import marshmallow_dataclass
from marshmallow.validate import Range
@dataclass
class City:
name: str
district: str
subject: str
population: int = field(metadata={'validate': Range(min=1, max=1000000)})
email: str = field(default="", metadata={"load_default": "",
"load_only": True})
coords: dict = field(default_factory=dict)
cities_list = [
{"coords": {
"lat": "52.65",
"lon": "90.08333"
},
"district": "Сибирский",
"name": "Абаза",
"population": 14816,
"subject": "Хакасия"
},
{"coords": {
"lat": "53.71667",
"lon": "91.41667"
},
"district": "Сибирский",
"name": "Абакан",
"population": 187239,
"subject": "Хакасия"
}]
# Создание схемы на основе датакласса
CitySchema = marshmallow_dataclass.class_schema(City)
# Расширяем своей схемой, схему созданную на основе датакласса
class CoordsSchema(Schema):
lat = fields.Float()
lon = fields.Float()
class CitySchemaExtended(CitySchema):
coords = fields.Nested(CoordsSchema, required=True)
# Десериализация
city_schema = CitySchemaExtended(many=True)
cities = city_schema.load(cities_list)
print(cities)
# Сериализация
result = city_schema.dump(cities)
print(result)
Этот код демонстрирует процесс создания, сериализации и десериализации данных о городах, используя библиотеки dataclasses
для определения структуры данных и marshmallow
вместе с marshmallow_dataclass
для обработки сериализации/десериализации и валидации данных.
Сначала определяется класс City
с использованием декоратора @dataclass
. Класс включает поля: имя города, район, субъект, население, электронная почта и координаты. Для поля population
задается валидация с помощью встроенного валидатора Range
, который ограничивает значения от 1 до 1 000 000, обеспечивая, что население будет в этом диапазоне. Поле email
задано как необязательное с пустым значением по умолчанию и помечено для использования только при загрузке данных (load_only=True
), что означает, оно не будет включено при сериализации объектов обратно в JSON. Для coords
используется фабрика по умолчанию для создания пустого словаря.
Затем создается список словарей cities_list
, который содержит данные о двух городах, включая их координаты, район, название, население и субъект. Эти данные предназначены для десериализации, то есть преобразования из формата JSON в объекты Python.
С помощью функции class_schema
из marshmallow_dataclass
автоматически создается схема Marshmallow для класса City
. Это упрощает процесс, поскольку не требуется вручную определять поля схемы и их валидацию.
Для улучшения обработки координат создается дополнительная схема CoordsSchema
и расширяется исходная схема CitySchema
, заменяя поле coords
на вложенную схему CoordsSchema
с помощью fields.Nested
. Это обеспечивает дополнительную валидацию координат, гарантируя, что они соответствуют ожидаемому формату с плавающей точкой.
- Десериализация: Используя расширенную схему
CitySchemaExtended
, данные изcities_list
преобразуются в список объектовCity
. Этот процесс включает в себя валидацию данных согласно определенным правилам и преобразование их в объекты Python. - Сериализация: Объекты
City
затем сериализуются обратно в формат JSON. В этом процессе поляemail
исключаются из результатов, так как они были помечены какload_only
.
В конце, результаты десериализации и последующей сериализации выводятся на экран, показывая, как исходные данные были преобразованы в объекты и обратно в JSON.
В целом, этот код иллюстрирует мощные возможности сочетания dataclasses
и marshmallow
для обработки сложных структур данных с автоматической валидацией и удобным преобразованием между форматами объектов Python Python и JSON. Это особенно полезно при разработке API, где требуется эффективная обработка данных, приходящих в различных форматах, и их валидация согласно определенным правилам или ограничениям. Использование marshmallow_dataclass
значительно упрощает этот процесс, позволяя разработчикам сосредоточиться на бизнес-логике приложения, вместо ручного определения и поддержки схем данных и валидационной логики.
Ключевые моменты, которые стоит заметить в этом процессе:
- Автоматизация создания схем:
marshmallow_dataclass
автоматически создает схемы на основе датаклассов, значительно сокращая объем кода, необходимого для их ручного определения. - Валидация данных: Использование встроенных и кастомных валидаторов Marshmallow в
metadata
поля датакласса позволяет легко применять сложные правила валидации без дополнительного кода. - Гибкая кастомизация: Несмотря на автоматизацию, разработчики имеют возможность кастомизировать процесс сериализации/десериализации, расширяя автоматически сгенерированные схемы или добавляя дополнительные поля и валидаторы.
- Управление сериализацией/десериализацией: Через метаданные можно указывать, какие поля должны быть включены или исключены из процесса, а также управлять поведением по умолчанию, например, задавая значения по умолчанию для отсутствующих данных.
Класс Meta
внутри схемы Marshmallow используется для настройки поведения схемы в целом. Один из параметров, который можно определить внутри класса Meta
, — это unknown
. Этот параметр управляет тем, как схема должна обрабатывать неизвестные поля, то есть поля, которые присутствуют в ваших данных, но не определены в схеме.
Когда вы устанавливаете unknown = INCLUDE
в классе Meta
вашей схемы, это указывает Marshmallow, что необходимо принимать и включать неизвестные поля в результат сериализации или десериализации. Это может быть полезно, когда вы работаете с динамическими данными, структура которых может меняться или содержать дополнительные поля, не критичные для вашей бизнес-логики.
EXCLUDE
: Это значение говорит Marshmallow игнорировать неизвестные поля. Если входные данные содержат поля, которых нет в схеме, они будут просто игнорироваться и не включены в выходные данные. Это значение по умолчанию.RAISE
: Указывает Marshmallow генерировать ошибку при обнаружении неизвестных полей. Это полезно для сценариев, когда вы хотите строго контролировать структуру ваших данных и быть уверенным, что они соответствуют ожидаемому формату.
fields
: Список строк, определяющий, какие поля должны быть включены в сериализацию. Если определен, только поля, указанные в этом списке, будут обработаны.additional
: Список строк, определяющий дополнительные поля, которые следует включить в сериализацию наряду с теми, что уже определены в схеме.load_only
: Список полей, которые должны использоваться только для десериализации и не должны сериализоваться обратно в выходные данные.dump_only
: Список полей, которые должны использоваться только для сериализации и не учитываться при десериализации.dateformat
: Строка, определяющая формат даты, который будет использоваться для полей с датами при их сериализации.ordered
: Булево значение, указывающее, должны ли поля в выходных данных следовать в том порядке, в котором они определены в схеме.
Использование класса Meta
предоставляет мощный инструмент для настройки поведения ваших схем Marshmallow, позволяя точно контролировать процесс сериализации и десериализации данных, обеспечивая гибкость и соответствие требованиям вашего приложения.