为什么Python的json.dumps拒绝从我的对象中序列化字符串?

时间:2016-06-16 02:47:11

标签: python json django string serialization

使用Python json.dumps()时,我的Django站点没有正确地序列化我的对象。我有一个专门用于将数据注入Chart.js组件的类:

class ChartData:
    def __init__(self):
        self.labels = []
        self.data = []
        self.background_colours = []
        self.hover_background_colours = []

    def add_datum(self, label, datum, background_colour=None, hover_background_colour=None):
        self.labels.append(label)
        self.data.append(datum)
        self.background_colours.append(background_colour)
        self.hover_background_colours.append(hover_background_colour)

    def get_converted_data(self):
        return json.dumps({'labels': self.labels, 'data': self.data, 'background_colours': self.background_colours,
                           'hover_background_colours': self.hover_background_colours})

调用方法将Quiz作为输入,并添加其关联的Subject项中的数据:

def get_subject_chart_data(quiz):
    subjects = Subject.objects.filter(question__quizquestion__quiz=quiz).distinct()
    chart_data = ChartData()
    for subject in subjects:
        chart_data.add_datum(subject.name, subject.question_set.filter(quizquestion__quiz=quiz).count())

    return chart_data.get_converted_data()

然后将此转换后的数据发送到context注入要呈现的页面。

def get_context_data(self, **kwargs):
    context = super(QuizDetail, self).get_context_data(**kwargs)
    quiz = self.get_object()

    context['subject_chart_data'] = self.get_subject_chart_data(quiz)

    return context

在此之后,它被呈现为{% include %}语句,作为chart_data参数传入:

{% include 'snippets/pie_chart.html' with chart_data=subject_chart_data chart_id='subject_chart' chart_height=400 chart_width=400 %}

最后,HTML使用传入的chart_data呈现图表:

<canvas id="{{ chart_id }}" width="{{ chart_width }}" height="{{ chart_height }}"></canvas>
<script>
    var ctx = document.getElementById("{{ chart_id }}");
    var chart = new Chart(ctx, {
        type: 'doughnut',
        data: {
            labels: {{ chart_data.labels|safe }},
        datasets: [
            {
                data: {{ chart_data.data|safe }},
                backgroundColor: {{ chart_data.background_colours|safe }}
            }]
        }
    });
</script>

鉴于我在Python docs的示例中使用了json.dumps(),我希望它可以正常工作。

>>> json.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}])
'["foo", {"bar": ["baz", null, 1.0, 2]}]'

然而,结果如下:

var chart = new Chart(ctx, {
    type: 'doughnut',
    data: {
        labels: ,
    datasets: [
        {
            data: ,
            backgroundColor: 
        }]
    }
});

但是,如果我将ChartData的每个属性传递给json.dumps(),那么:

def get_converted_data(self):
    return {'labels': json.dumps(self.labels), 'data': json.dumps(self.data),
            'background_colours': json.dumps(self.background_colours),
            'hover_background_colours': json.dumps(self.hover_background_colours)}

没有任何问题:

var chart = new Chart(ctx, {
        type: 'doughnut',
        data: {
            labels: ["Geo"],
        datasets: [
            {
                data: [2],
                backgroundColor: [null],
                hoverBackgroundColor: [null]
            }]
        }
    });

1 个答案:

答案 0 :(得分:1)

获取转换数据的第二个版本有效,因为它是一个字典,您的模板需要chartdata点数据和图表数据点背景颜色。模板正在访问dict以获取这些值,这就是为什么当你使用带有json编码值的dict时它可以工作。第一个版本json将整个dict编码为django模板无法读取的字符串。

您可以将python变量的dict转换为json编码变量的dict,如下所示:

data = {'labels': self.labels, 'data': self.data, 'background_colours': self.background_colours, 'hover_background_colours': self.hover_background_colours}
data_json = {k:json.dumps(v) for k, v in data.items()}