I am pretty new to the django-rest-framework, so could use some help.
I have an object with a TextField that is a string containing JSON.
I'm using django-rest-framework to serialize the whole object as JSON. However, this one string that is already JSON gets serialized as an encoded string containing the JSON rather than the JSON itself.
How can I tell the serializer to send this field as-is rather than trying to transform this string to JSON? Is there some sort of "ignore" decorator or override I can use? Or can I pre-parse this JSON before serializing?
This is the difference between having:
{"data": data}
and
{"data": "data"}
The latter being more of a nuisance to use on the client side...
You can simply decode the json into python object:
json_obj = json.loads(model.json_text)
Once you serialize your object, replace this field with the decoded object:
data = serializer.data
data["field"] = json_obj
return Response(data)
I solved this another way:
1: use a JSON-Field for the JSON content (django-jsonfield
or django-json-field
should be fine). These then will to loads/dumps as needed
2: in my serializer, use the transform-method to prevent the data added as string to the response
class MyModelSerializer(serializers.ModelSerializer):
def transform_myjsonfield(self, obj, value):
return obj.myjsonfield
class Meta:
model = MyModel
If you need write-access, you only have to add a method validate_myjsonfield
which converts back.
(of course, this could be also done with a custom DRF serializer field.
Here is what works for me on, djangorestframework==3.9.1
:
import json
from rest_framework import serializers
from .models import WeatherLocation
class WeatherLocationSerializer(serializers.ModelSerializer):
LocationId = serializers.CharField(source='location_id')
City = serializers.CharField(source='city')
Region = serializers.CharField(source='region')
Name = serializers.CharField(source='name')
Country = serializers.CharField(source='country')
WeatherForecastLongTermTimePeriods = serializers.JSONField(required=False, allow_null=True,
source='weather_forecast_long_term_time_periods')
WeatherForecastShortTermTimePeriods = serializers.JSONField(required=False, allow_null=True,
source='weather_forecast_short_term_time_periods')
def to_representation(self, instance):
ret = super(WeatherLocationSerializer, self).to_representation(instance)
ret['WeatherForecastLongTermTimePeriods'] = json.loads(ret['WeatherForecastLongTermTimePeriods'])
ret['WeatherForecastShortTermTimePeriods'] = json.loads(ret['WeatherForecastShortTermTimePeriods'])
return ret
class Meta:
model = WeatherLocation
fields = ['LocationId', 'City', 'Region', 'Name', 'Country',
'WeatherForecastLongTermTimePeriods', 'WeatherForecastShortTermTimePeriods', ]
I thought there would be an easier way to do this, but by changing the behaviour of to_representation
, I can convert my text fields to JSON. For reference, here is my models.py
:
from django.db import models
class WeatherLocation(models.Model):
"""
Weather app schema, from southparc
"""
location_id = models.CharField(primary_key=True, null=False, blank=False, default=None, max_length=254,
editable=True)
region = models.CharField(max_length=2, null=False, blank=False)
city = models.CharField(null=False, blank=False, max_length=254)
province = models.CharField(null=True, blank=True, max_length=254)
name = models.CharField(null=True, blank=True, max_length=254)
country = models.CharField(null=True, blank=True, max_length=254)
# JSON fields
weather_forecast_long_term_time_periods = models.TextField(default="", blank=True)
weather_forecast_short_term_time_periods = models.TextField(default="", blank=True)
# Dates
created_date = models.DateTimeField(auto_now_add=True)
modified_date = models.DateTimeField(auto_now=True)
Hope that helps. If you use a JSONField
that is supported by Postgres, I'm sure you won't need to do this. I'm using a TextField to save my JSON here. I thought that specifying the field type as serializers.JSONField
on the serializer would be enough but its not the case.