Поле JSON иногда содержит строку, иногда объект

Я использую платформу 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)
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
Четыре эффективных способа центрирования блочных элементов в CSS
Четыре эффективных способа центрирования блочных элементов в CSS
У каждого из нас бывали случаи, когда нам нужно отцентрировать блочный элемент, но мы не знаем, как это сделать. Даже если мы реализуем какой-то...
0
0
20
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вам нужно установить 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)

Надеюсь, это поможет.

Я боюсь, что это не сработало, потому что, когда получен только идентификатор продавца, он получен в виде строки, и проверка выдает эту ошибку: {'merchant': {'non_field_errors': [ErrorDetail(string='Invalid data. Expected a словарь, но получил str.', code='invalid')]}}

rcx935 17.05.2022 07:34

Тогда вы можете добавить примеры данных JSON в пост?

Metalgear 17.05.2022 08:50
Ответ принят как подходящий

Вы можете переопределить 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.

Другие вопросы по теме