【问题标题】:Easy JSON encoding with Python使用 Python 轻松进行 JSON 编码
【发布时间】:2011-04-10 09:47:48
【问题描述】:

我对 python 很陌生(我使用 python 3),我正在尝试用一个字符串和两个列表作为 JSon 中的成员序列化一个类。我发现python标准中有一个json lib,但似乎我需要手动实现一个序列化方法。是否有一个 JSON 编码器,我可以简单地传递一个对象,并将序列化的对象作为字符串接收,而无需实现序列化方法。 示例:

class MyClass:
    pass

if __name__ == '__main__':
    my_name = "me"
    my_list = {"one","two"}
    my_obj = MyClass()
    my_obj.name = my_name;
    my_obj.my_list = my_list


    serialized_object = JSONserializer.serialize(my_obj).

谢谢。

【问题讨论】:

  • Python 版本重要吗?我的意思是,你能在 2.x 中做到这一点,但在 3.0 中无法做到吗?
  • 是的,大多数库似乎已经从 2.x 更改为 3。

标签: python json serialization


【解决方案1】:

不知道任何预先构建的东西,但如果您的对象足够简单,您可以编写一个。覆盖 JSONEncoder 中的默认方法以查看 inspect.getmembers(obj)(inspect 是获取 __dict__ 中属性集的更易读的方式。

#!/usr/bin/env python3

import inspect
from json import JSONEncoder


class TreeNode:

    def __init__(self, value, left=None, right=None):
        self.value = value
        self.left = left
        self.right = right


class ObjectJSONEncoder(JSONEncoder):

    def default(self, reject):
        is_not_method = lambda o: not inspect.isroutine(o)
        non_methods = inspect.getmembers(reject, is_not_method)
        return {attr: value for attr, value in non_methods
                if not attr.startswith('__')}


if __name__ == '__main__':
    tree = TreeNode(42,
        TreeNode(24),
        TreeNode(242),
    )
    print(ObjectJSONEncoder().encode(tree))

更新:@Alexandre Deschamps 说 isroutine 在某些输入方面比 is 方法效果更好。

【讨论】:

  • 感谢您的回答,除了两件事之外,它几乎可以解决问题。 is_not_method = lambda o: not inspect.ismmethod(o) 似乎也需要 not inspect.isroutine(o) 语句。看起来在 python 中,内置方法是一个极限情况。另外,我的班级需要一个要序列化的列表。看起来列表中的元素没有被序列化。
  • @Alexandre Deschamps:我不明白你的意思......如果你将__main__ 中的这些数字更改为数字列表,它会很好地序列化。
  • 好的,我刚刚发现我是问题所在。我使用 {} 而不是 [] 来制作列表。正如我所说,我是这门语言的新手。它工作正常。只需将“not inspect.isroutine”添加到您的示例中,以防其他人需要它。非常感谢您的宝贵时间。
  • @Alexandre Deschamps:啊!那不是列表,那是 set 数据类型。它没有顺序,因此没有直接映射到 JSON 数据类型。如果您在其中粘贴if isinstance(reject, set): return list(reject),它将起作用 - 它只会为生成的 JSON 数组中的集合中的值分配任意顺序。
  • 我们好像同时看到了:P
【解决方案2】:

您希望json 库如何知道如何序列化任意类?

在您的情况下,如果您的课程足够简单,您也许可以摆脱类似

foo = FooObject() # or whatever
json_string = json.dumps(foo.__dict__)

只是序列化对象的成员。

反序列化需要类似于

foo_data = json.loads(json_string)
foo = FooObject(**foo_data)

【讨论】:

  • 不,它似乎不起作用,因为我的班级有两个成员,一个字符串和一个字符串列表
  • 它适用于我:gist.github.com/574291。如果您的对象真的只有两个成员,一个字符串和一个字符串列表,那么序列化将起作用。我使用的反序列化技术依赖于对象的 __init__ 函数来获取与成员同名的参数。有关工作示例,请参见上面的要点。
  • @WillMcCutchen 感谢使用dict 的灵感。我想做类似的事情,虽然我的对象(来自 SOAP 请求)没有 __dict__ 方法,但调用 dict(soapObj) 给了我一个打印得很好的 JSON 字符串。我也是 python 新手,这不是一个显而易见的技术,所以很高兴你提到它!
【解决方案3】:

JSONEncoder 类怎么样?

更新

我一定跳过了关于类中包含的数据的部分。如果你想在不需要扩展编码器的情况下对任意 Python 对象进行合理的序列化,那么也许你可以使用 picklejson 的组合。酸洗时,使用protocol = 0将数据序列化为人类可读的ASCII。

【讨论】:

  • 仍然,我需要编码一个类,而不仅仅是一个简单的类型或数组。这个类似乎需要一个手动定义的序列化方法来序列化一个类。也许我错了,因为我是语言新手,但是当我测试时,我得到了。
  • pickle 人类可读的想法是:(i__main__ Map p0 (dp1 S'towers' p2 (lp3 (i__main__ Tower p4 (dp5 S'attack' p6 I10 sbasS'creeps' p7 (lp8 S'one string creep in a list' p9 asb. 与 JSON 相比,人类可读性差。
  • 用“可打印”代替“人类可读”。我的观点是,如果他坚持使用 JSON 来洗牌 python 对象,那么协议 0 泡菜可以安全地序列化为 JSON 字符串。
猜你喜欢
  • 1970-01-01
  • 2021-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-30
  • 2022-08-11
  • 1970-01-01
相关资源
最近更新 更多