Flask jsonify:对象不可迭代

4

我有一个类,长得像这样:

class Sound(SoundJsonSerializer):
    def __init__(self, name, length):
        self.name = name
        self.length = length

在这里,SoundJsonSerializer使我的自定义JSONEncoder能够将此对象序列化为JSON:

{
    "name": "foobar",
    "length": 23.4
}

现在我想让我的一个请求准确地响应上述JSON。
@app.route('/sounds/<soundid>')
def get_sound(soundid):
    s = Sound("foobar", 23.4)
    return jsonify(s)

产生一个错误,声称s不可迭代,这是正确的。我该如何使方法返回我想要的JSON?

我知道我可以通过从我的Sound对象中显式地创建一个字典来实现这一点,就像这样:

    return jsonify({"name": s.name, "length": s.length})

但这种方法对我来说看起来很丑陋。有没有更好的方法实现我的目标?

实际上,我更喜欢你认为“丑”的那种方式。如果你经常这样做,那么也许可以将创建字典变成一个函数,它接受对象和代表要包含(或排除)的属性的字符串列表,并创建字典(使用 dir()getattr())。 - Mark Hildreth
2
是的,这个问题非常烦人,所以我决定修补Flask使其正常工作 - Nick Retallack
2个回答

3
您可以尝试这个解决方法:
class Sound():
    def __init__(self, name, length):
        self.name = name
        self.length = length

@app.route('/sounds/<soundid>')
def get_sound(soundid):
    s = Sound('foobar', 23.4)
    return jsonify(s.__dict__)

2
这不是一个好的做法,因为它暴露了所有类的内部,而不仅仅是他想要的属性。 - Paolo Casciello
1
@PaoloCasciello是正确的,可能只有JSON表示中我想要的属性子集。这就是我定制的JSONEncoder所关心的事情。 - Sandra

2
你可以通过几种不同的方式来完成这个任务。为了确保你只返回想要的内容,最安全的方法是这样做:
class Sound():
    name = None
    length = None
    test = "Test"

    def __init__(self, name, length):
        self.name = name
        self.length = length

@admin_app.route('/sounds/<sound_id>')
def get_sound(sound_id):
    s = Sound('foobar', sound_id)
    return jsonify(vars(s))

通过在类级变量中定义name = None, length = None,您可以使用vars()而不是__dict__

当您通过__init__实例化类并在那里设置变量时,jsonify仅返回您通过__init__设置的内容。

以上代码的结果:

{
"length": "1",
"name": "foobar"
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接