barciewicz
barciewicz

Reputation: 3773

Django : how to serialize model's text field without rendering backslashes

I have a model like this:

class Activity(models.Model):
    date_added = models.DateTimeField(auto_now_add=True)
    start_date = models.DateTimeField(default=datetime.datetime.now)
    data = models.TextField() # stores activity's JSON in text format, not as Python object
    number = models.IntegerField(default=0)
    athlete = models.ForeignKey(Athlete, on_delete=models.CASCADE, default=None)

Field data stores JSON as text.

I am using the following serializer for this model:

from rest_framework import serializers
from .models import Activity


class ActivitySerializer(serializers.ModelSerializer):

    class Meta:
        model = Activity
        fields = ("date_added", "start_date", "data", "number", "athlete")

Now when I do the following in the Django shell:

>>>from explorer_api.models import Activity
>>>fromt explorer_api.serializers import ActivitySerializer
>>>activity = Activity.objects.latest('id')
>>>serializer = ActivitySerializer(activity)
>>>serializer.data

The output is generated fine:

>>> serializer.data
{'date_added': '2018-11-19T21:10:29.324522Z', 'start_date': '2018-11-15T05:36:10Z', 'athlete': 1, 'data': '{"resource_state":3,"athlete":{"id":3255732,"resource_state":1},"name":"Morning Ride","distance":33605.0,"moving_time":5067,"elapsed_time":5067,"total_elevation_gain":59.0,

However, when I try to user the JSON renderer:

>>>from rest_framework.renderers import JSONrenderer
>>>JSONRenderer.render(serializer.data)

The activity.data gets rendered with backslashes to escape double qoutes:

>>> JSONRenderer().render(serializer.data)
b'{"date_added":"2018-11-19T21:10:29.324522Z","start_date":"2018-11-15T05:36:10Z","data":"{\\"resource_state\\":3,\\"athlete\\":{\\"id\\":3255732,\\"resource_state\\":1},\\"name\\":\\"Morning Ride\\",\\"distance\\":33605.0,

How can I prevent this? I want my API to expose pure JSON text.

Upvotes: 0

Views: 1156

Answers (1)

ruddra
ruddra

Reputation: 51948

You can override the serializers.Field to create a new SerilizerField and change its behavior. For example:

import json

class JSONSerializerField(serializers.Field):

    def to_representation(self, obj):
        try:
            return json.loads(obj)
        except (ValueError, Exception) as e:
            # log exception
            return obj

    def to_internal_value(self, data):
        return data

class ActivitySerializer(serializers.HyperlinkedModelSerializer):
    data = JSONSerializerField()

    class Meta:
        model = Activity
        fields = ('data', 'id', 'date_added', 'start_date')

Upvotes: 1

Related Questions