在Python中序列化用户定义的类

时间:2021-07-23 05:00:10

got a question regarding serializing classes that I've defined. I have some classes like

有一个关于序列化我定义的类的问题。我有一些课程

class Foo:
     def __init__(self, x, y):
          self.x = x, self.y = y

     def toDict(self):
          return dict(Foo = dict(x = self.x, y = self.y))

then a class that can contain multiple Foos, such as:

然后是一个可以包含多个Foos的类,例如:

class Bar:
     def __init__(self):
          self.foos = [Foo(a, b), Foo(1, 2)]

While that's a gross oversimplification of the real structure (it gets much, much more nested than that), that's a pretty decent overview. The actual data for this is coming from a pseudo-XML file without any actual structure, so I wrote a parser according to the spec given to me, so I now have all the data in a series of classes I've defined, with actual structure.

虽然这是对真实结构的粗略过度简化(它得到了更多,更多嵌套),但这是一个相当不错的概述。这个实际数据来自一个没有任何实际结构的伪XML文件,因此我根据给出的规范编写了一个解析器,所以我现在将所有数据都放在我定义的一系列类中,实际结构体。

What I'm wanting to do is take this data I have and spit it out into JSON, but I really don't see a good way (I'm new to Python, this is my first real project with it).

我想要做的就是把我拥有的这些数据并将其吐出到JSON中,但我真的看不到一个好方法(我是Python的新手,这是我第一次使用它的真实项目)。

I've defined a method in Foo, toDict(), that creates a dictionary out of the information, but that obviously isn't going to work out like I hope when I try to serialize Bar, with the multiple Foos.

我在Foo中定义了一个方法toDict(),它从信息中创建了一个字典,但是当我尝试使用多个Foos序列化Bar时,这显然不会像我希望的那样。

Does anyone have a great way of doing this? This has been a pretty much non-stop learning/codefest the past few days and I'm out of ideas for this, which is the last part of the project. I know about the JSON module for Python, but that doesn't help me with this particular problem of getting my data into a dictionary (or something similar) that I can pass to json.dump().

有没有人有这样做的好方法?在过去的几天里,这是一个非常不间断的学习/代码节目,我对此缺乏想法,这是该项目的最后一部分。我知道Python的JSON模块,但这并没有帮助我解决这个将数据放入字典(或类似的东西)的特殊问题,我可以传递给json.dump()。

Let me know if I can clarify in any way.

如果我能以任何方式澄清,请告诉我。

Thanks, T.J.

谢谢,T.J。

3 个解决方案

#1


5  

Several comments. First:

几条评论。第一:

  • xml.dom.minidom is a built-in Python DOM implementation. Obviously if the file isn't actually XML you won't be able to use it's builtin parsing functions, but it looks like you're building a tree-like structure out of the file anyway, in which case you might as well use a minidom.
  • xml.dom.minidom是一个内置的Python DOM实现。显然,如果文件实际上不是XML,你将无法使用它的内置解析函数,但看起来你无论如何都要从文件中构建一个树状结构,在这种情况下你也可以使用minidom命名。

OK, henceforth I'll assume that you have a good reason for writing your own tree-style structure instead of using the builtins.

好的,从此以后我会假设您有充分的理由编写自己的树型结构而不是使用内置结构。

  • Are you sure the nodes should be classes? That seems like an awful lot of structure when all you really seem to need is a bunch of nested dicts:

    你确定节点应该是类吗?当你真正需要的是一堆嵌套的dicts时,这似乎是一个非常多的结构:

    root = {
        "foo1": { "bar1": "spam", "bar2": "ham"},
        "foo2": { "baz1": "spam", "baz2": "ham"},
    }
    

    You get the idea.

    你明白了。

OK, maybe you're sure that you need the individual nodes to be classes. In that case, they should all inherit from some BaseNode class, right? After all, they are fundamentally similar things.

好吧,也许您确定需要将各个节点作为类。在这种情况下,它们都应该从一些BaseNode类继承,对吧?毕竟,它们基本上是相似的东西。

  • In that case, define a BaseNode.serialise method which effectively prints some information about itself and then calls serialise on all of its children. This is a recursive problem; you might as well use a recursive solution unless your tree is really really really nested.

    在这种情况下,定义一个BaseNode.serialise方法,该方法有效地打印一些关于自身的信息,然后在其所有子节点上调用serialise。这是一个递归问题;你也可以使用递归解决方案,除非你的树真的真的嵌套了。

    The json library allows you to subclass the JSONEncoder to do this.

    json库允许您子类化JSONEncoder来执行此操作。

    >>> import json
    >>> class ComplexEncoder(json.JSONEncoder):
    ...     def default(self, obj):
    ...         if isinstance(obj, complex):
    ...             return [obj.real, obj.imag]
    ...         return json.JSONEncoder.default(self, obj)
    ...
    >>> dumps(2 + 1j, cls=ComplexEncoder)
    '[2.0, 1.0]'
    >>> ComplexEncoder().encode(2 + 1j)
    '[2.0, 1.0]'
    >>> list(ComplexEncoder().iterencode(2 + 1j))
    ['[', '2.0', ', ', '1.0', ']']
    

#2


0  

Can't suggest anything with JSON, but you can use the Pickle module to serialize your objects in binary format.

无法使用JSON建议任何内容,但您可以使用Pickle模块以二进制格式序列化对象。

#3


0  

You might consider using jsonpickle package --- it basically allows you to convert most picklable objects to json.

您可以考虑使用jsonpickle包---它基本上允许您将大多数可选对象转换为json。

#1


5  

Several comments. First:

几条评论。第一:

  • xml.dom.minidom is a built-in Python DOM implementation. Obviously if the file isn't actually XML you won't be able to use it's builtin parsing functions, but it looks like you're building a tree-like structure out of the file anyway, in which case you might as well use a minidom.
  • xml.dom.minidom是一个内置的Python DOM实现。显然,如果文件实际上不是XML,你将无法使用它的内置解析函数,但看起来你无论如何都要从文件中构建一个树状结构,在这种情况下你也可以使用minidom命名。

OK, henceforth I'll assume that you have a good reason for writing your own tree-style structure instead of using the builtins.

好的,从此以后我会假设您有充分的理由编写自己的树型结构而不是使用内置结构。

  • Are you sure the nodes should be classes? That seems like an awful lot of structure when all you really seem to need is a bunch of nested dicts:

    你确定节点应该是类吗?当你真正需要的是一堆嵌套的dicts时,这似乎是一个非常多的结构:

    root = {
        "foo1": { "bar1": "spam", "bar2": "ham"},
        "foo2": { "baz1": "spam", "baz2": "ham"},
    }
    

    You get the idea.

    你明白了。

OK, maybe you're sure that you need the individual nodes to be classes. In that case, they should all inherit from some BaseNode class, right? After all, they are fundamentally similar things.

好吧,也许您确定需要将各个节点作为类。在这种情况下,它们都应该从一些BaseNode类继承,对吧?毕竟,它们基本上是相似的东西。

  • In that case, define a BaseNode.serialise method which effectively prints some information about itself and then calls serialise on all of its children. This is a recursive problem; you might as well use a recursive solution unless your tree is really really really nested.

    在这种情况下,定义一个BaseNode.serialise方法,该方法有效地打印一些关于自身的信息,然后在其所有子节点上调用serialise。这是一个递归问题;你也可以使用递归解决方案,除非你的树真的真的嵌套了。

    The json library allows you to subclass the JSONEncoder to do this.

    json库允许您子类化JSONEncoder来执行此操作。

    >>> import json
    >>> class ComplexEncoder(json.JSONEncoder):
    ...     def default(self, obj):
    ...         if isinstance(obj, complex):
    ...             return [obj.real, obj.imag]
    ...         return json.JSONEncoder.default(self, obj)
    ...
    >>> dumps(2 + 1j, cls=ComplexEncoder)
    '[2.0, 1.0]'
    >>> ComplexEncoder().encode(2 + 1j)
    '[2.0, 1.0]'
    >>> list(ComplexEncoder().iterencode(2 + 1j))
    ['[', '2.0', ', ', '1.0', ']']
    

#2


0  

Can't suggest anything with JSON, but you can use the Pickle module to serialize your objects in binary format.

无法使用JSON建议任何内容,但您可以使用Pickle模块以二进制格式序列化对象。

#3


0  

You might consider using jsonpickle package --- it basically allows you to convert most picklable objects to json.

您可以考虑使用jsonpickle包---它基本上允许您将大多数可选对象转换为json。