django:控制json序列化

1 投票
4 回答
3861 浏览
提问于 2025-04-16 12:36

在Django中,有没有办法控制json的序列化?下面这段简单的代码会返回一个json格式的对象:

co = Collection.objects.all()
c = serializers.serialize('json',co)

生成的json大概是这样的:

[
    {
        "pk": 1,
        "model": "picviewer.collection",
        "fields": {
            "urlName": "architecture",
            "name": "\u0413\u043e\u0440\u043e\u0434 \u0438 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430",
            "sortOrder": 0
        }
    },
    {
        "pk": 2,
        "model": "picviewer.collection",
        "fields": {
            "urlName": "nature",
            "name": "\u041f\u0440\u0438\u0440\u043e\u0434\u0430",
            "sortOrder": 1
        }
    },
    {
        "pk": 3,
        "model": "picviewer.collection",
        "fields": {
            "urlName": "objects",
            "name": "\u041e\u0431\u044a\u0435\u043a\u0442\u044b \u0438 \u043d\u0430\u0442\u044e\u0440\u043c\u043e\u0440\u0442",
            "sortOrder": 2
        }
    }
]

你可以看到,它以一种方式序列化数据,让你可以在需要的时候重新创建整个模型——这没问题,但对于我来说,这样的格式在简单的JS ajax中不太方便:我想尽量减少数据流量,让整个过程更清晰。

我做的事情是创建了一个视图,把对象传递给一个.json模板,然后这个模板会生成更“好看”的json输出,像这样:

[
{% if collections %}
    {% for c in collections %}
{"id": {{c.id}},"sortOrder": {{c.sortOrder}},"name": "{{c.name}}","urlName": "{{c.urlName}}"}{% if not forloop.last %},{% endif %}
    {% endfor %}
{% endif %}
]

这样做是有效的,输出的结果看起来好多了:

[
    {
        "id": 1,
        "sortOrder": 0,
        "name": "Город и архитектура",
        "urlName": "architecture"
    },
    {
        "id": 2,
        "sortOrder": 1,
        "name": "Природа",
        "urlName": "nature"
    },
    {
        "id": 3,
        "sortOrder": 2,
        "name": "Объекты и натюрморт",
        "urlName": "objects"
    } 
]

不过,我有点担心我的解决方案使用了模板(这增加了处理的步骤,可能会影响性能),而且如果我更新模型的话,还需要手动维护。

我在想,json的生成应该是模型的一部分(如果我错了请纠正我),应该用原生的python-json和Django的实现来完成,但我不知道怎么去掉我不想要的部分。

还有一点,即使我限制了要序列化的字段,它的id总是会在元素容器外面显示,而是以“pk”的形式呈现。

4 个回答

0

与其自己写代码,不如让Piston来帮你把Django模型转换成JSON格式。默认情况下,它只会把模型的字段转换,不会包含额外的信息。而且你可以很简单地选择要包含或排除哪些字段,甚至是相关的字段。这样就不需要额外的模板,代码也很少。

2

我建议你使用json库来编码你的数据,而不是自己手动构造类似json的字符串。上面的代码似乎没有正确处理转义字符,这就是一个问题。而自己写序列化程序其实没什么好处,反而容易出错。

2

这真的很简单。给你一个快速的例子:

from django.http import HttpResponse
from django.utils import simplejson

def simple_view(request):
    response = {'string': "test",
                'number': 42,
                'array': [1, 2, 3],
                'js_object': dict(foo="bar")}
    return HttpResponse(simplejson.dumps(response),
                        mimetype="application/json")

这个视图会返回以下内容的等价JSON:

{"string": "test",
 "number": 42,
 "array": [1, 2, 3],
 "js_object": {foo: "bar"}}

补充一下:没错,Assaf Lavie说得对,你的模板可能会输出无效的JSON。

撰写回答