JSON 字段有时包含字符串,有时包含对象

JSON field sometimes contains string, sometimes object

我正在使用 Django 休息框架来验证从接收金融交易的 API 收到的 JSON。序列化程序已经工作了几年了。 JSON 中的商家字段将始终包含商家作为带有商家 ID、名称等的嵌套对象。但现在我有时只收到商家 ID 作为字符串并且 JSON 现在无法验证.

如何设置我的序列化程序以允许商家字段中的字符串或对象?

基本上商户字段需要接受以下任一:

merchant = MerchantSerializer(required=False, allow_null=True)
merchant = serializers.CharField(required=False, max_length=50)

serializers.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)

您需要将 name 字段的 required 设置为 false。

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)

希望对您有所帮助。

您可以重写 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