简体   繁体   English

JSON在列表/二进制中序列化Python中的对象

[英]JSON serialize objects in Python in list / diconary

I am very new to Python and I have this rather large and complex data structure that is a list of dictionaries with lists of different objects. 我对Python还是很陌生,我有一个相当大而复杂的数据结构,它是一个字典列表,其中包含不同对象的列表。 When I try and convert this to JSON via json.dumps() I get the standard 当我尝试通过json.dumps()将其转换为JSON时,我得到了标准

TypeError: <...> is not JSON serializable

I did some research, and most of the answers point to a standard way of writing a custom encoder, which is fine, I can do that. 我做了一些研究,大多数答案都指向编写自定义编码器的标准方法,这很好,我可以做到。 However, I would like to be able to send my whole data structure to json.dumps() and not loop through everything, figure out what class it is, and build a json object from scratch. 但是,我希望能够将我的整个数据结构发送到json.dumps(),而不是遍历所有内容,弄清楚它是什么类,并从头开始构建json对象。

Is there a way to add an encoder/decoder functions to the python class itself, so when I send a complex data structure to json.dumps, the class itself knows what to do. 有没有一种方法可以向python类本身添加编码器/解码器功能,所以当我向json.dumps发送复杂的数据结构时,该类本身知道该怎么做。

is there some magic to_json or some way of adding a custom decoder to that class that gets called when the json.dumps runs into it? 有什么神奇的to_json或某种方法添加自定义解码器到当json.dumps遇到该类时被调用的类吗?

The custom encoder class handles that for you when you use json.dumps(my_object, cls=MyCustomJsonEncoder) . 当您使用json.dumps(my_object, cls=MyCustomJsonEncoder)时,自定义编码器类将为您处理该问题。 Your custom encoder would override the default method, which takes self and the object o to encode; 您的自定义编码器会覆盖default方法,该default方法使用self和对象o进行编码; test for the different types that need custom serialization, and pass the rest to the default with super(MyCustomJsonEncoder, self).default(o) . 测试需要自定义序列化的不同类型,然后使用super(MyCustomJsonEncoder, self).default(o)将其余类型传递给默认类型。

A simple example that I often use is as follows: 我经常使用的一个简单示例如下:

class JSONEncoder(json.JSONEncoder):
    """
    Enhancement of base JSONEncoder, also handling these objects:
     * datetime.datetime
     * decimal.Decimal
     * uuid.UUID
    """

    def default(self, o):
        if isinstance(o, Decimal):
            return float(o)
        elif isinstance(o, UUID):
            return str(o)
        elif isinstance(o, datetime):
            return {
                '__type__': 'datetime',
                '__value__': o.isoformat(),
            }
        return super(JSONEncoder, self).default(o)

    @staticmethod
    def dumps(obj):
        return json.dumps(obj, cls=JSONEncoder)

As Steven Wolfe stated in this thread , you may want to look into jsonpickle . 正如史蒂文·沃尔夫(Steven Wolfe)在此线程中所述 ,您可能需要研究jsonpickle This library allows for encoding and decoding of complex Python object. 该库允许对复杂的Python对象进行编码和解码。

You could use it this way: 您可以通过以下方式使用它:

import jsonpickle

f = open(filename, 'w')
encoded_string = jsonpickle.encode(obj)
f.write(encoded_string)
f.close()

And to retrieve the data as Python object, simply use the jsonpickle.decode(encoded_string) method. 要将数据检索为Python对象,只需使用jsonpickle.decode(encoded_string)方法。 As the documentation says : 如文档所述:

The new object has the same type and data, but essentially is now a copy of the original. 新对象具有相同的类型和数据,但现在基本上是原始对象的副本。

I think that could work well for you. 我认为这可能对您有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM