1

I am struggling to figure out how to write a custom serializer in DRF to parse a complex JSON data structure that is being passed to an endpoint. The JSON looks like this:

{
    "name": "new",
    "site": "US",
    "data": {
        "settings": [],
        "meta": {
            "meta1":{}
        }
    }
}

Here is my backend code:

# views.py
class SaveData(views.APIView):
    def post(self, request, *args, **kwargs):
        name = request.POST.get('name')
        site = request.POST.get('site')
        data = request.POST.get('data')

But data always returns None. On closer inspection into the request object, the incoming JSON looks like this:

# POST attribute of request object
'name' = 'new'
'site' = 'US'
'data[settings][0] = ''
'data[meta][meta1][] = ''

Basically it looks like the nested JSON objects associated with the data key are not getting properly serialized into Python dict and list objects. I've been looking for examples of custom DRF serializers but most of the ones I've found have been for serializing Django models, but I don't need to do that. The incoming data does not directly map to my models; instead I need to do some processing before I save any of the data.

Does anyone have any advice on a custom serializer that would properly convert the data JSON into proper Python objects? I started with this but it throws an exception (When a serializer is passed a 'data' keyword argument you must call '.is_valid()' before attempting to access the serialized '.data' representation. You should either call '.is_valid()' first, or access '.initial_data' instead.). Here is my code with the custom serializer I created:

# serializers.py
class SaveDataSerializer(serializers.Serializer):
    name = serializers.CharField()
    site = serializers.CharField()
    data = serializers.DictField()

    def create(self, validated_data):
        return dict(**validated_data)

Thanks.

stimko68
  • 67
  • 2
  • 7

1 Answers1

0

I was able to solve my problem by converting the JS object to JSON when passing it to $.ajax, which then DRF was able to correctly parse into Python objects. Here's a snippet of the jQuery I'm using:

$.ajax({
    url: '/api/endpoint',
    type: 'POST',
    contentType: 'application/json',
    data: JSON.stringify(ajaxData),
    done: function(data) {}
    ...
})

Note though that jQuery will default to x-www-urlencoded as the Content-Type if you don't specify anything. Since I'm using the JSON.stringify() method to explicitly convert the ajaxData object to a JSON string the Content-Type needed to be explicitly set as well.

I got the idea from this SO answer: Convert Object to JSON string

Of course, this doesn't really answer my original question, but this is another solution that is simpler and works like I wanted. By doing this I didn't have to create any custom serializers, but I did have to modify my API view like so:

class SaveData(views.APIView):
    def post(self, request, *args, **kwargs):
        name = request.data.get('name')
        site = request.data.get('site')
        data = request.data.get('data')

After doing this the expected object types are returned

>>> type(name)
str
>>> type(site)
str
>>> type(data)
dict
Community
  • 1
  • 1
stimko68
  • 67
  • 2
  • 7