5

I am working on writing serializers for an existing API for the purpose of auto-generating OpenAPI documentation for the project. One of the issues I'm running into is defining serializers to validate the returned data from some of the views.

Here is the structure of the data:

{
    "airmass_data": {
        "site-A": {
            "times": ["2021-09-09T09:54","2021-09-09T10:04"],
            "airmasses": [2.900041850251779, 2.687634707193725]
        },
        "site-B": {
            "times": ["2021-09-09T09:54","2021-09-09T10:04"],
            "airmasses": [2.900041850251779, 2.687634707193725]
        },
                ...
    },
    "airmass_limit": 3.19
}

There can be an arbitrary number of "site-X" keys, and they are dynamically generated - which is definitely part of my issue.

Here is how I've set up my serializers, which I think mostly matches my dictionary structure:

class SiteAirmassDatumSerializer(serializers.Serializer):
    times = serializers.ListField(child=serializers.CharField())
    airmasses = serializers.ListField(child=serializers.FloatField())


class SiteAirmassSerializer(serializers.Serializer):
    site = SiteAirmassDatumSerializer(source='*')


class AirmassSerializer(serializers.Serializer):
    airmass_data = SiteAirmassSerializer(source='*')
    airmass_limit = serializers.FloatField()

However, when passing my dictionary into the the serializer and attempting to validate it, the serializer.errors attribute has:

{
  "airmass_data": {
    "site": [
      "This field is required."
    ]
  }
}

Is there a good way to write a set of serializers such that it deals with dynamically generated keys? I am mostly trying to write this to validate the general structure of the returned dictionary - not necessarily the keys within it. The reason I am interested in using Serializers is to utilize DRF's OpenAPI generation features.

EDIT:

Have also tried using a DictField in the serializers, like so:

class SiteAirmassDatumSerializer(serializers.Serializer):
    times = serializers.ListField(child=serializers.CharField())
    airmasses = serializers.ListField(child=serializers.FloatField())


class SiteAirmassSerializer(serializers.Serializer):
    site = DictField(child=SiteAirmassDatumSerializer(), source='*')


class AirmassSerializer(serializers.Serializer):
    airmass_data = DictField(child=SiteAirmassSerializer(), source='*')
    airmass_limit = serializers.FloatField()

When attempting to validate the aforementioned structure, I get the following error:

{
  "airmass_data": {
    "site-A": {
      "site": [
        "This field is required."
      ]
    }
  }
}

1 Answer 1

1

I suggest changing your data structure and use a list instead of dict:

{
    "airmass_data": [
         {
            "site_name": "site-A"
            "times": ["2021-09-09T09:54","2021-09-09T10:04"],
            "airmasses": [2.900041850251779, 2.687634707193725]
        },
        {
            "site_name": "site-B"
            "times": ["2021-09-09T09:54","2021-09-09T10:04"],
            "airmasses": [2.900041850251779, 2.687634707193725]
        },
                ...
    ],
    "airmass_limit": 3.19
}
Sign up to request clarification or add additional context in comments.

1 Comment

This is probably the best long-term strategy as it seems to be more in-line with the Django Serializer model of statically structured data. Was more curious if there's a workaround to my particular issue, but it seems like it goes against some of Django's assumptions about serializing data.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.