【问题标题】:django-rest-framework: How Do I Serialize a Field That Already Contains JSON?django-rest-framework:如何序列化已经包含 JSON 的字段?
【发布时间】:2014-04-05 01:41:03
【问题描述】:

我对 django-rest-framework 还是很陌生,所以需要一些帮助。

我有一个带有 TextField 的对象,它是一个包含 JSON 的字符串。

我正在使用 django-rest-framework 将整个对象序列化为 JSON。但是,这个已经是 JSON 的字符串会被序列化为包含 JSON 而不是 JSON 本身的编码字符串。

如何告诉序列化程序按原样发送此字段,而不是尝试将此字符串转换为 JSON?我可以使用某种“忽略”装饰器或覆盖吗?或者我可以在序列化之前预先解析这个 JSON 吗?

这就是拥有的区别:

{"data": data}

{"data": "data"}

后者在客户端使用起来更麻烦...

【问题讨论】:

    标签: python json django serialization django-rest-framework


    【解决方案1】:

    我用另一种方式解决了这个问题:

    1:对 JSON 内容使用 JSON 字段(django-jsonfielddjango-json-field 应该没问题)。然后这些将根据需要加载/转储

    2:在我的序列化程序中,使用转换方法来防止将数据作为字符串添加到响应中

    class MyModelSerializer(serializers.ModelSerializer):
        def transform_myjsonfield(self, obj, value):
            return obj.myjsonfield
    
        class Meta:
            model = MyModel
    

    如果你需要写访问,你只需要添加一个方法validate_myjsonfield 来转换回来。

    (当然,这也可以通过自定义 DRF 序列化器字段来完成。

    【讨论】:

    【解决方案2】:

    您可以简单地将 json 解码为 python 对象:

    json_obj = json.loads(model.json_text)
    

    序列化对象后,将此字段替换为解码的对象:

    data = serializer.data
    data["field"] = json_obj
    return Response(data)
    

    【讨论】:

    • 非常好,谢谢。我希望有一个简单的解决方案,因为我不可能是第一个尝试这个的人。 :)
    【解决方案3】:

    这对我有用,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', ]
    

    我认为有一种更简单的方法可以做到这一点,但是通过更改to_representation 的行为,我可以将我的文本字段转换为 JSON。供参考,这里是我的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)
    

    希望对您有所帮助。如果您使用 Postgres 支持的 JSONField,我相信您不需要这样做。我在这里使用 TextField 来保存我的 JSON。我认为在序列化程序上将字段类型指定为serializers.JSONField 就足够了,但事实并非如此。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-02
      • 2022-08-08
      • 2013-07-07
      • 1970-01-01
      • 2020-06-09
      • 1970-01-01
      • 1970-01-01
      • 2013-11-15
      相关资源
      最近更新 更多