Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/311.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Django Rest框架:将嵌套json字段中的数据序列化为普通对象_Python_Json_Django_Serialization_Django Rest Framework - Fatal编程技术网

Python Django Rest框架:将嵌套json字段中的数据序列化为普通对象

Python Django Rest框架:将嵌套json字段中的数据序列化为普通对象,python,json,django,serialization,django-rest-framework,Python,Json,Django,Serialization,Django Rest Framework,我想将非平面结构序列化为一个平面对象。 下面是我收到的一个API调用示例(很遗憾,我无法控制它): 我想将其序列化为以下模型: class Issue(models.Model): jira_id = models.IntegerField() jira_id = models.CharField() summary = models.CharField() class Change(models.Model): issue = models.ForeignKe

我想将非平面结构序列化为一个平面对象。 下面是我收到的一个API调用示例(很遗憾,我无法控制它):

我想将其序列化为以下模型:

class Issue(models.Model):
    jira_id = models.IntegerField()
    jira_id = models.CharField()
    summary = models.CharField()

class Change(models.Model):
    issue = models.ForeignKey(Issue)
    timestamp = models.DataTimeField()
正如您所看到的,model
Issue
的字段
summary
与JSON数据中的
id
key
位于同一个对象上

接下来是我的序列化程序:

    class ChangeSerializer(serializers.ModelSerializer):
        """Receives complex data from jira and converts into objects."""

        issue = JiraIssueSerializer()
        timestamp = TimestampField(source='created_at')

        class Meta:
            model = Change
            fields = ('issue', 'timestamp')

        def create(self, validated_data):
            super(serializers.ModelSerializer, self).create(validated_data=validated_data)
            jira_issue = JiraIssueSerializer(data=validated_data)
            issue = Issue.objects.get(jira_issue)
            self.created_at = datetime.utcnow()
            change = Change(**validated_data)
            return change



    class JiraIssueSerializer(serializers.ModelSerializer):
        """Issue serializer."""
        id = serializers.IntegerField(source='jira_id')
        key = serializers.CharField(source='jira_key')
        summary = serializers.CharField()   ### I want field to work!
        # fields = serializers.DictField(child=serializers.CharField())

        class Meta:
            model = Issue
            fields = ('id', 'key',
               'summary',
            )

        def to_internal_value(self, data):
           # ret = super(serializers.ModelSerializer,   self).to_internal_value(data)
           ret = {}
           # ret = super().to_internal_value(data)
           ret['jira_id'] = data.get('id', None)
           ret['jira_key'] = data.get('key', None)
           jira_issue_fields_data = data.get('fields')
           if jira_issue_fields_data or 1:
               summary = jira_issue_fields_data.get('summary', None)
               ret.update(summary=summary)
            print('to_internal_value', ret)
            return ret

         def to_representation(self, instance):
            ret = {}
            ret = super().to_representation(instance)
            fields = {}
            fields['summary'] = instance.summary
            ret.update(fields=fields)
            print(ret)
            return ret
我可以很好地处理JSON中
issue
对象中的字段。 但是如何向JiraIssueSerializer添加一些字段,如
摘要
?它们不是
问题
对象的直接字段,而是位于子循环
字段
中。 我的看法是:

  • 再制作一个模型
    字段
    来保存它们,但这很可笑。我不需要它,我的API严格依赖于外部结构

  • 制作一些
    .to_内部字段()
    转换器。但在这种情况下,我必须手动验证并准备我的
    问题中的所有字段
    ,并重复几次。此外,如果字段
    摘要
    未登记在序列化程序中,则序列化程序无法使用它或验证失败

  • DictField
    添加到序列化程序(在代码中注释)并从中获取数据。好吗?如何验证它?同样,我有一个干净的代码结构

接下来,我要解析并保存changelog数据

如何更好地处理此类结构


谢谢大家!

我建议您创建自己的自定义序列化程序来接收数据。您可以这样做:

from rest_framework import serializers

class MySerializer(serializers.Serializer):
    """
    Custom serializer
    """
    id = serializers.IntegerField(read_only=True)
    name = serializers.CharField()


    def create(self, validated_data):
        """Create a new object"""
        validated_data['custom_value'] = 0 # you can manipulate and restructure data here if you wish
        return MyModel.objects.create(**validated_data)

然后,您可以在
create()
函数中随心所欲地操作数据。您还可以创建嵌套的自定义序列化程序来解析此数据。

最后,在django rest框架的测试中找到了解决方案。

您可以轻松地定义嵌套序列化程序,它将充当容器并将数据提取到普通对象。像这样:

    class NestedSerializer1(serializers.Serializer):
        a = serializers.IntegerField()
        b = serializers.IntegerField()

    class NestedSerializer2(serializers.Serializer):
        c = serializers.IntegerField()
        d = serializers.IntegerField()

    class TestSerializer(serializers.Serializer):
        nested1 = NestedSerializer1(source='*')
        nested2 = NestedSerializer2(source='*')

    data = {
        'nested1': {'a': 1, 'b': 2},
        'nested2': {'c': 3, 'd': 4}
     }

     serializer = TestSerializer(data=self.data)
     assert serializer.is_valid()

     assert serializer.validated_data == {
        'a': 1, 
        'b': 2,
        'c': 3, 
        'd': 4
    }

文档是处理问题的重要部分

基本上,您希望创建一个具有嵌套值的单独类,如下所示:

class UserSerializer(serializers.Serializer):
    email = serializers.EmailField()
    username = serializers.CharField(max_length=100)

class CommentSerializer(serializers.Serializer):
    user = UserSerializer()
    content = serializers.CharField(max_length=200)
    created = serializers.DateTimeField()

不,它会为你证明我找到了规避它的方法。这是一种标准的计划方式!你能解释一下你是如何解决这个问题的吗?谢谢@TonyWang,我创建了3个序列化程序:顶级的
TestSerializer
,以及2个嵌套的
NestedSerializer1
NestedSerializer2
。然后在顶层I set
source=“*”
,这样所有嵌套字段都将传播到父序列化程序。因此,您可能有一个dict
{“a”:1,“b”:2,“c”:3,“d”:4}
,它将被序列化为json对象,包含两个字段
nested1
nested2
。第一个包含字段
a
b
。第二个-
c
d
。具有适当的价值观。结果:
{'nested1':{'a':1,'b':2},'nested2':{'c':3,'d':4}
class UserSerializer(serializers.Serializer):
    email = serializers.EmailField()
    username = serializers.CharField(max_length=100)

class CommentSerializer(serializers.Serializer):
    user = UserSerializer()
    content = serializers.CharField(max_length=200)
    created = serializers.DateTimeField()