django-rest-framework: How Do I Serialize a Field

2020-03-03 07:12发布

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

3条回答
叛逆
2楼-- · 2020-03-03 07:18

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)
查看更多
放我归山
3楼-- · 2020-03-03 07:23

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.

查看更多
仙女界的扛把子
4楼-- · 2020-03-03 07:34

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.

查看更多
登录 后发表回答