Я использую платформу Django rest для проверки JSON, полученного от API, который получает финансовые транзакции. Сериализатор работает уже несколько лет. Поле продавца в JSON всегда будет содержать продавца как вложенный объект с идентификатором продавца, именем и т. д. Но теперь я иногда получаю только идентификатор продавца в виде строки, и теперь JSON не проходит проверку.
Как мне настроить свой сериализатор, чтобы он разрешал либо строку, либо объект в поле продавца?
По сути, поля продавца должны принимать одно из следующих значений:
merchant = MerchantSerializer(required=False, allow_null=True)
merchant = serializers.CharField(required=False, max_length=50)
сериализаторы.py
class MerchantSerializer(serializers.Serializer):
id = serializers.CharField(required=True, max_length=50)
name = serializers.CharField(required=True, max_length=100)
atm = serializers.BooleanField(required=False, allow_null=True)
address = AddressSerializer(required=False, allow_null=True)
logo = serializers.URLField(required=False, allow_null=True, max_length=500, min_length=None, allow_blank=True)
class DataSerializer(serializers.Serializer):
account_id = serializers.CharField(required=True, max_length=50)
amount = serializers.IntegerField(required=True)
created = serializers.DateTimeField()
currency = serializers.CharField(required=True, max_length=3)
description = serializers.CharField(required=True, max_length=250)
id = serializers.CharField(required=True, max_length=50)
category = serializers.CharField(required=True, max_length=100)
decline_reason = serializers.CharField(required=False, allow_null=True, allow_blank=True, max_length=100)
merchant = MerchantSerializer(required=False, allow_null=True)
counterparty = CounterpartySerializer(required=False, allow_null=True)
metadata = MetadataSerializer(required=False, allow_null=True)
Вам нужно установить required
значение false для поля name
.
class MerchantSerializer(serializers.Serializer):
id = serializers.CharField(required=True, max_length=50)
name = serializers.CharField(required=False, max_length=100) # this field
atm = serializers.BooleanField(required=False, allow_null=True)
address = AddressSerializer(required=False, allow_null=True)
logo = serializers.URLField(required=False, allow_null=True, max_length=500, min_length=None, allow_blank=True)
Надеюсь, это поможет.
Тогда вы можете добавить примеры данных JSON в пост?
Вы можете переопределить to_internal_value
таким образом, чтобы он пытался проанализировать переданные данные. В приведенном ниже решении он просто проверяет, являются ли данные словарем, и устанавливает их в словарь, если это не так.
Это решение позволит сериализатору принимать строку, но внутри сериализатора она станет словарем, содержащим только ключ id
.
class MerchantSerializer(serializers.Serializer):
id = serializers.CharField(required=True, max_length=50)
# other fields ...
def to_internal_value(self, data):
parsed_data = data
if not isinstnace(parsed_data, dict):
parsed_data = { "id": data }
return super().to_internal_value(parsed_data)
Вам, вероятно, придется изменить некоторые проверки в сериализаторе, чтобы он мог получать только id
.
Я боюсь, что это не сработало, потому что, когда получен только идентификатор продавца, он получен в виде строки, и проверка выдает эту ошибку: {'merchant': {'non_field_errors': [ErrorDetail(string='Invalid data. Expected a словарь, но получил str.', code='invalid')]}}