如何使类JSON可序列化

Ser*_*gey 730 python serialization json

如何使Python类可序列化?

一个简单的课程:

class FileItem:
    def __init__(self, fname):
        self.fname = fname
Run Code Online (Sandbox Code Playgroud)

我该怎么做才能得到输出:

>>> import json

>>> my_file = FileItem('/foo/bar')
>>> json.dumps(my_file)
TypeError: Object of type 'FileItem' is not JSON serializable
Run Code Online (Sandbox Code Playgroud)

没有错误(__CODE__)

Onu*_*rım 565

这是一个简单的功能的简单解决方案:

.toJSON() 方法

而不是JSON可序列化类,实现序列化方法:

import json

class Object:
    def toJSON(self):
        return json.dumps(self, default=lambda o: o.__dict__, 
            sort_keys=True, indent=4)
Run Code Online (Sandbox Code Playgroud)

所以你只需要将其命名为序列化:

me = Object()
me.name = "Onur"
me.age = 35
me.dog = Object()
me.dog.name = "Apollo"

print(me.toJSON())
Run Code Online (Sandbox Code Playgroud)

将输出:

{
    "age": 35,
    "dog": {
        "name": "Apollo"
    },
    "name": "Onur"
}
Run Code Online (Sandbox Code Playgroud)

  • 非常有限.如果你有一个字典{"foo":"bar","baz":"bat"},它将很容易地序列化为JSON.如果你有{"foo":"bar","baz":MyObject()},那么你就不能.理想情况是嵌套对象以递归方式序列化为JSON,而不是显式. (72认同)
  • 它仍然有效.你错过了`o .__ dict ___`.试试你自己的例子:`class MyObject():def __init __(self):self.prop = 1 j = json.dumps({"foo":"bar","baz":MyObject()},默认= lambda o :o .__ dict __)` (27认同)
  • 这个解决方案是可逆的吗?即从json重建对象是否容易? (14认同)
  • @cglacet那是因为他没有使类可序列化,他只是做了一个吐出JSON字符串的方法。这不是问题的正确答案,它更像是针对特殊情况的黑客攻击。但正确的是上面的。如果您需要将 YourObject 序列化为另一个 ParentObject 的一部分/内容,则需要创建一个编码器。 (11认同)
  • 744人没听懂问题 (8认同)
  • 这不适用于`datetime.datetime`实例.它抛出以下错误:`'datetime.datetime'对象没有属性'__dict __'` (5认同)
  • 该问题特别询问有关制作 json.dumps() 的问题。不是如何自己实现所有 JSON 序列化。 (5认同)
  • 您可以使用 `default=vars` 代替 `default=lambda o: o.__dict__`。 (3认同)
  • 我可能会迟到,但要用类中的类序列化“datetime”: `json.dumps(myObject, default=lambda o: o.isoformat() if (isinstance(o, datetime.datetime)) else o.__dict__, sort_keys =True, indent=4)` - 不需要实现额外的功能。 (3认同)
  • @JCLeitãoNo.您可以拥有两个具有相同字段的不同类.该类的对象a和b(可能具有相同的属性)将具有相同的`a .__ dict__` /`b .__ dict__`. (2认同)
  • 以下内容适用于没有`__dict__`的任何内容:`def _try(o):try:return o .__ dict__除了:return str(o)`和`def to_JSON(self):return json.dumps( self,default = lambda o:_try(o),sort_keys = True,indent = 0,separators =(',',':')).replace('\n','')` (2认同)
  • 我一定遗漏了一些东西,但这似乎不起作用(即,`json.dumps(me)` 不调用 `Object` 的 `toJSON` 方法。 (2认同)

Man*_*dan 507

您对预期产量有所了解吗?例如,这会吗?

>>> f  = FileItem("/foo/bar")
>>> magic(f)
'{"fname": "/foo/bar"}'
Run Code Online (Sandbox Code Playgroud)

在这种情况下,你只能打电话json.dumps(f.__dict__).

如果您想要更多自定义输出,那么您必须子类化JSONEncoder并实现自己的自定义序列化.

有关一个简单的例子,请参见下文.

>>> from json import JSONEncoder
>>> class MyEncoder(JSONEncoder):
        def default(self, o):
            return o.__dict__    

>>> MyEncoder().encode(f)
'{"fname": "/foo/bar"}'
Run Code Online (Sandbox Code Playgroud)

然后将此类json.dumps()作为clskwarg 传递给方法:

json.dumps(cls=MyEncoder)
Run Code Online (Sandbox Code Playgroud)

如果您还想要解码,那么您必须object_hook为该JSONDecoder课程提供自定义.例如

>>> def from_json(json_object):
        if 'fname' in json_object:
            return FileItem(json_object['fname'])
>>> f = JSONDecoder(object_hook = from_json).decode('{"fname": "/foo/bar"}')
>>> f
<__main__.FileItem object at 0x9337fac>
>>> 
Run Code Online (Sandbox Code Playgroud)

  • 使用`__dict__`在所有情况下都不起作用.如果在实例化对象后尚未设置属性,则可能无法完全填充"__dict__".在上面的例子中,你没问题,但如果你有你想要编码的类属性,那么这些属性将不会列在`__dict__`中,除非它们已在类'__init__`调用中被修改或通过其他方式修改在对象被实例化之后. (35认同)
  • 如果在新的样式类上使用`__slots__`,@ KrisHardy`__dict__`也不起作用. (8认同)
  • +1,但用作object-hook的`from_json()`函数应该有一个`else:return json_object`语句,因此它也可以处理一般对象. (7认同)
  • 您可以使用上面的自定义`JSONEncoder`来创建自定义协议,例如检查`__json_serializable__`方法的存在并调用它以获取对象的JSON可序列化表示.这将与其他Python模式保持一致,例如`__getitem ___,`__str __,`__eq__`和`__len__`. (7认同)
  • `__dict__`也不会递归工作,例如,如果对象的属性是另一个对象. (2认同)

gec*_*cco 154

对于更复杂的类,您可以考虑使用jsonpickle工具:

jsonpickle是一个Python库,用于将复杂Python对象与JSON进行序列化和反序列化.

用于将Python编码为JSON的标准Python库,例如stdlib的json,simplejson和demjson,只能处理具有直接JSON等效的Python原语(例如,词典,列表,字符串,整数等).jsonpickle构建在这些库之上,允许将更复杂的数据结构序列化为JSON.jsonpickle具有高度可配置性和可扩展性,允许用户选择JSON后端并添加额外的后端.

(链接到PyPi上的jsonpickle)

  • 来自C#,这正是我所期待的.简单的一个班轮,没有乱搞班级. (24认同)
  • @user5359531 你可以使用 `obj = jsonpickle.decode(file.read())` 和 `file.write(jsonpickle.encode(obj))`。 (4认同)
  • jsonpickle 很棒。它非常适合具有多个级别的巨大、复杂、凌乱的对象 (2认同)
  • 专门针对django 的一个问题:使用jsonpickle 序列化会话数据是否与pickle 存在相同的漏洞?(如此处所述 https://docs.djangoproject.com/en/1.11/topics/http/sessions/#bundled-serializers)? (2认同)

Jef*_*kin 78

TLDR:复制粘贴下面的选项 1 或选项 2

完整答案:
让 Pythonjson模块与你的类一起工作

又名,解决:json.dumps({ "thing": YOUR_CLASS() })


解释:

  • 是的,存在可靠的解决方案
  • 不,没有Python“官方”解决方案
    • 通过官方解决方案,我的意思是(截至 2023 年)无法向您的类添加方法(如toJSONJavaScript)和/或无法使用内置 json 模块注册您的类。当执行类似的操作时json.dumps([1,2, your_obj]),Python 不会检查查找表或对象方法。
    • 我不确定为什么其他答案没有解释这一点
    • 最接近的官方方法可能是andyhasit 的答案,即从字典继承。然而,对于许多自定义类(例如 AdvancedDateTime 或 pytorch 张量)来说,从字典继承并不能很好地工作。
  • 理想的解决方法是这样的:
    • def __json__(self)将方法添加到您的类中
    • 变异json.dumps以检查__json__方法(影响所有地方,甚至导入 json 的 pip 模块)
    • 注意:修改内置内容通常不太好,但是这种更改应该没有副作用,即使它被不同的代码库多次应用。它在运行时是完全可逆的(如果模块想要撤消修改)。无论好坏,这都是目前能做的最好的事情。


选项 1:让模块进行修补


pip install json-fix
Fancy John 的答案的扩展+打包版本,谢谢@FancyJohn)

your_class_definition.py

import json_fix

class YOUR_CLASS:
    def __json__(self):
        # YOUR CUSTOM CODE HERE
        #    you probably just want to do:
        #        return self.__dict__
        return "a built-in object that is naturally json-able"
Run Code Online (Sandbox Code Playgroud)

就是这样。


用法示例:

from your_class_definition import YOUR_CLASS
import json

json.dumps([1,2, YOUR_CLASS()], indent=0)
# '[\n1,\n2,\n"a built-in object that is naturally json-able"\n]'
Run Code Online (Sandbox Code Playgroud)

要使json.dumpsNumpy 数组、Pandas DataFrame 和其他第 3 方对象正常工作,请参阅模块(只有大约 2 行代码,但需要解释)。




它是如何工作的?出色地...

选项 2:自己修补 json.dumps


注意:这种方法被简化了,它在已知的边缘情况下失败(例如:如果您的自定义类继承自dict或另一个内置类),并且它错过了控制外部类(numpy 数组、日期时间、数据帧、张量等)的 json 行为。

some_file_thats_imported_before_your_class_definitions.py

from your_class_definition import YOUR_CLASS
import json

json.dumps([1,2, YOUR_CLASS()], indent=0)
# '[\n1,\n2,\n"a built-in object that is naturally json-able"\n]'
Run Code Online (Sandbox Code Playgroud)

your_class_definition.py

# Step: 1
# create the patch
from json import JSONEncoder
def wrapped_default(self, obj):
    return getattr(obj.__class__, "__json__", wrapped_default.default)(obj)
wrapped_default.default = JSONEncoder().default
   
# apply the patch
JSONEncoder.original_default = JSONEncoder.default
JSONEncoder.default = wrapped_default
Run Code Online (Sandbox Code Playgroud)

_

所有其他答案似乎都是“序列化自定义对象的最佳实践/方法”

其中,文档中已对此进行了介绍(搜索“complex”以获取编码复数的示例)

  • 在整个代码库中修改“json.dumps”有点激进,但这显然是最好的解决方案。 (5认同)
  • 好的解决方案。json.loads 是否有等效项? (2认同)
  • 遗憾的是没有@Sam,而且从根本上来说是不可能的;json-dumping 实际上是一种单向操作。例如:考虑一个 BigInt 类,它将自身转换为 json.dumps 的字符串。现在考虑 json 文件中某处的随机字符串值。也许该字符串值包含全数字,这是否意味着它应该作为 BigInt 加载?如果字符串恰好包含全数字,但应该保留为字符串,该怎么办?json.loads 无法知道,因此您必须使用您知道应该是 BigInt 的字符串执行类似“BigInt.from_json(a_str)”的操作。 (2认同)

and*_*sit 71

大多数答案涉及将调用更改为json.dumps(),这并不总是可行或可取的(例如,它可能发生在框架组件中).

如果你想能够按原样调用 json.dumps(obj),那么一个简单的解决方案是继承自dict:

class FileItem(dict):
    def __init__(self, fname):
        dict.__init__(self, fname=fname)

f = FileItem('tasks.txt')
json.dumps(f)  #No need to change anything here
Run Code Online (Sandbox Code Playgroud)

如果您的类只是基本数据表示,那么这种方法很有用,因为您可以始终明确地设置键.

  • @kfmfe04 这个答案解决了您无法控制调用“json.dumps”的代码的情况。 (7认同)
  • 虽然“点访问”仍然缺失:( (4认同)
  • 这个解决方案有点hacky - 对于真正的生产质量解决方案,用 jsonpickle.encode() 和 jsonpickle.decode() 替换 json.dumps() 和 json.loads() 。您将避免编写丑陋的样板代码,最重要的是,如果您能够 pickle 对象,您应该能够使用 jsonpickle 序列化它,而无需样板代码(复杂的容器/对象就可以工作)。 (3认同)
  • 这确实是一个不错的解决方案:)我相信我的情况是这样。好处:通过使对象具有init类来传达对象的“形状”,它固有地可序列化,并且可以解释为__repr__。 (2认同)
  • 啊,这似乎有效!谢谢,不知道为什么这不是公认的答案。我完全同意更改 `dumps` 不是一个好的解决方案。顺便说一句,在大多数情况下,您可能希望将 `dict` 继承与委托一起使用,这意味着您将在类中拥有一些 `dict` 类型的属性,然后将该属性作为参数作为参数传递,例如 `super ().__init__(self.elements)`。 (2认同)

Pau*_*tas 39

另一种选择是将JSON转储包装在自己的类中:

import json

class FileItem:
    def __init__(self, fname):
        self.fname = fname

    def __repr__(self):
        return json.dumps(self.__dict__)
Run Code Online (Sandbox Code Playgroud)

或者,更好的是,从类中继承FileItem JsonSerializable类:

import json

class JsonSerializable(object):
    def toJson(self):
        return json.dumps(self.__dict__)

    def __repr__(self):
        return self.toJson()


class FileItem(JsonSerializable):
    def __init__(self, fname):
        self.fname = fname
Run Code Online (Sandbox Code Playgroud)

测试:

>>> f = FileItem('/foo/bar')
>>> f.toJson()
'{"fname": "/foo/bar"}'
>>> f
'{"fname": "/foo/bar"}'
>>> str(f) # string coercion
'{"fname": "/foo/bar"}'
Run Code Online (Sandbox Code Playgroud)

  • 嗨,我真的不喜欢这种"自定义编码器"的方法,如果你能使你的班级json可连接,那就更好了.我试着尝试一无所获.有没有想法如何做到这一点.问题是json模块针对内置的python类型测试你的类,甚至说自定义类使你的编码器:).可以伪造吗?所以我可以对我的班级做一些事情,所以它表现得像json模块的简单列表?我尝试__subclasscheck__和__instancecheck__但没有. (2认同)
  • 这并不会使对象可序列化为 json 类。它只提供了一个获取返回的 json 字符串的方法(简单)。因此 `json.dumps(f)` 将失败。这不是被问到的。 (2认同)

Jas*_*n S 39

我喜欢Onur的答案,但会扩展为包含一个可选的toJSON()方法来对象自行序列化:

def dumper(obj):
    try:
        return obj.toJSON()
    except:
        return obj.__dict__
print json.dumps(some_big_object, default=dumper, indent=2)
Run Code Online (Sandbox Code Playgroud)

  • 我其实很喜欢这个; 但是,而不是`try-catch`可能会在obj .__ attrs __()中执行类似`if'toJSON'的操作:`...以避免静默失败(如果由于某些其他原因导致toJSON()失败不存在)......可能导致数据损坏的故障. (10认同)
  • @thclark 据我了解,idomatic python 要求宽恕,而不是许可,所以 try- except 是正确的方法,但应该捕获正确的异常,在本例中是 AttributeError 。 (8认同)
  • @phil 现在年纪大了几岁,也更聪明了,我同意你的观点。 (4认同)
  • 这确实应该显式地捕获“AttributeError” (4认同)
  • 如果在“obj.toJSON()”内部引发“AttributeError”怎么办? (3认同)

use*_*520 33

正如许多其他答案中提到的,您可以传递一个函数来json.dumps将不是默认支持的类型之一的对象转换为支持的类型。令人惊讶的是,他们都没有提到最简单的情况,即使用内置函数vars将对象转换为包含其所有属性的字典:

json.dumps(obj, default=vars)
Run Code Online (Sandbox Code Playgroud)

请注意,这仅涵盖基本情况,如果您需要对某些类型(例如排除某些属性或没有属性的对象)进行更具体的序列化,则需要__dict__使用自定义函数或JSONEncoder其他答案中描述的 a 。

  • 对于某些对象,此方法将抛出“vars() 参数必须具有 __dict__ 属性” (18认同)
  • 感谢这一点,与内置正确定义的库一起使用非常简单。 (3认同)
  • 目前尚不清楚“default=vars”的含义,这是否意味着“vars”是默认的序列化器?如果不是:这并不能真正解决您无法影响“json.dumps”调用方式的情况。如果您只是将一个对象传递给一个库,并且该库在该对象上调用“json.dumps”,那么如果该库不以这种方式使用“dumps”,那么实现“vars”并没有真正的帮助。从这个意义上说,它相当于自定义的“JSONEncoder”。 (2认同)
  • 错误“vars() 参数必须具有 __dict__ 属性”的任何解决方法吗? (2认同)

tob*_*gue 24

前几天我遇到了这个问题,并为Python对象实现了一个更通用的版本,可以处理嵌套对象继承的字段:

import json
import inspect

class ObjectEncoder(json.JSONEncoder):
    def default(self, obj):
        if hasattr(obj, "to_json"):
            return self.default(obj.to_json())
        elif hasattr(obj, "__dict__"):
            d = dict(
                (key, value)
                for key, value in inspect.getmembers(obj)
                if not key.startswith("__")
                and not inspect.isabstract(value)
                and not inspect.isbuiltin(value)
                and not inspect.isfunction(value)
                and not inspect.isgenerator(value)
                and not inspect.isgeneratorfunction(value)
                and not inspect.ismethod(value)
                and not inspect.ismethoddescriptor(value)
                and not inspect.isroutine(value)
            )
            return self.default(d)
        return obj
Run Code Online (Sandbox Code Playgroud)

例:

class C(object):
    c = "NO"
    def to_json(self):
        return {"c": "YES"}

class B(object):
    b = "B"
    i = "I"
    def __init__(self, y):
        self.y = y

    def f(self):
        print "f"

class A(B):
    a = "A"
    def __init__(self):
        self.b = [{"ab": B("y")}]
        self.c = C()

print json.dumps(A(), cls=ObjectEncoder, indent=2, sort_keys=True)
Run Code Online (Sandbox Code Playgroud)

结果:

{
  "a": "A", 
  "b": [
    {
      "ab": {
        "b": "B", 
        "i": "I", 
        "y": "y"
      }
    }
  ], 
  "c": {
    "c": "YES"
  }, 
  "i": "I"
}
Run Code Online (Sandbox Code Playgroud)

  • 虽然这有点旧了..我面临一些循环导入错误。因此,我没有在最后一行中执行“return obj”,而是执行了“return super(ObjectEncoder, self).default(obj)”。参考[此处](http://stackoverflow.com/questions/14249115/serializing-output-to-json-valueerror-circular-reference-Detected) (2认同)

Fan*_*ohn 24

只需to_json在您的类中添加方法,如下所示:

def to_json(self):
  return self.message # or how you want it to be serialized
Run Code Online (Sandbox Code Playgroud)

并将此代码(来自此答案)添加到所有内容的顶部:

from json import JSONEncoder

def _default(self, obj):
    return getattr(obj.__class__, "to_json", _default.default)(obj)

_default.default = JSONEncoder().default
JSONEncoder.default = _default
Run Code Online (Sandbox Code Playgroud)

这将在导入时修补json模块,因此JSONEncoder.default()会自动检查特殊的"to_json()"方法,并使用它来编码对象(如果找到).

就像Onur说的那样,但这次你不必更新json.dumps()项目中的每一个.

  • 十分感谢!这是唯一允许我按照自己的意愿行事的答案:能够在不改变现有代码的情况下序列化对象.其他方法大多不适合我.该对象在第三方库中定义,序列化代码也是第三方.改变它们会很尴尬.使用您的方法,我只需要执行`TheObject.to_json = my_serializer`. (6认同)
  • 这是正确的答案。我做了一个小变化: ```import json _fallback = json._default_encoder.default json._default_encoder.default = lambda obj: getattr(obj.__class__, "to_json", _fallback)(obj) ``` (3认同)

Art*_*yan 17

一个非常简单的单行解决方案

import json

json.dumps(your_object, default=vars)
Run Code Online (Sandbox Code Playgroud)

结束!

下面是一个测试。

import json
from dataclasses import dataclass


@dataclass
class Company:
    id: int
    name: str

@dataclass
class User:
    id: int
    name: str
    email: str
    company: Company


company = Company(id=1, name="Example Ltd")
user = User(id=1, name="John Doe", email="john@doe.net", company=company)


json.dumps(user, default=vars)
Run Code Online (Sandbox Code Playgroud)

输出:

{
  "id": 1, 
  "name": "John Doe", 
  "email": "john@doe.net", 
  "company": {
    "id": 1, 
    "name": "Example Ltd"
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 我为我工作!在我看来,这是迄今为止最好的解决方案。 (3认同)
  • 这是迄今为止最好的解决方案。 (3认同)
  • 漂亮干净的一行字 \o/ (2认同)
  • 这是最好的解决方案 (2认同)

R H*_*R H 13

如果您使用的是Python3.5 +,则可以使用jsons。它将把您的对象(及其所有属性递归地)转换成字典。

import jsons

a_dict = jsons.dump(your_object)
Run Code Online (Sandbox Code Playgroud)

或者,如果您想要一个字符串:

a_str = jsons.dumps(your_object)
Run Code Online (Sandbox Code Playgroud)

或者如果您的班级实施了jsons.JsonSerializable

a_dict = your_object.json
Run Code Online (Sandbox Code Playgroud)

  • 如果您能够使用Python 3.7+,我发现将python类转换为字典和JSON字符串(反之亦然)的最干净的解决方案是将jsons库与[dataclasses](https://docs.python。 org / 3.7 / library / dataclasses.html)。到目前为止,对我有好处! (2认同)
  • 这是一个外部库,未内置在标准Python安装中。 (2认同)

try*_*000 11

import simplejson

class User(object):
    def __init__(self, name, mail):
        self.name = name
        self.mail = mail

    def _asdict(self):
        return self.__dict__

print(simplejson.dumps(User('alice', 'alice@mail.com')))
Run Code Online (Sandbox Code Playgroud)

如果使用标准json,你需要定义一个default函数

import json
def default(o):
    return o._asdict()

print(json.dumps(User('alice', 'alice@mail.com'), default=default))
Run Code Online (Sandbox Code Playgroud)

  • 我通过使用lambda```json.dumps(User('alice','alice@mail.com'),default = lambda x:x .__ dict __)`删除_asdict函数来简化此过程 (2认同)

Sun*_*Wei 7

最简单的答案

class Object(dict):
    def __init__(self):
        pass

    def __getattr__(self, key):
        return self[key]

    def __setattr__(self, key, value):
        self[key] = value

# test
obj = Object()
obj.name = "John"
obj.age = 25
obj.brothers = [ Object() ]
text = json.dumps(obj)
Run Code Online (Sandbox Code Playgroud)

现在它为您提供输出,不要对 json.dumps(...) 进行任何更改

'{"name": "John", "age": 25, "brothers": [{}]}'
Run Code Online (Sandbox Code Playgroud)


rib*_*mar 6

json在它可以打印的对象方面受到限制,并且jsonpickle(您可能需要a pip install jsonpickle)受到限制,因为它不能缩进文本.如果你想检查一个你不能改变它的类的对象的内容,我仍然找不到比以下更直接的方法:

 import json
 import jsonpickle
 ...
 print  json.dumps(json.loads(jsonpickle.encode(object)), indent=2)
Run Code Online (Sandbox Code Playgroud)

请注意,他们仍然无法打印对象方法.


Dan*_*nce 6

为了扑灭这场长达 11 年的火灾,我需要一个满足以下标准的解决方案:

  • 允许仅使用 FileItem 类的实例进行序列化json.dumps(obj)
  • 允许 FileItem 实例具有属性:fileItem.fname
  • 允许将 FileItem 实例提供给任何将使用以下方式序列化它的库json.dumps(obj)
  • 不需要传递任何其他字段json.dumps(如自定义序列化程序)

IE:

fileItem = FileItem('filename.ext')
assert json.dumps(fileItem) == '{"fname": "filename.ext"}'
assert fileItem.fname == 'filename.ext'
Run Code Online (Sandbox Code Playgroud)

我的解决方案是:

  • 让 obj 的类继承自dict
  • 将每个对象属性映射到底层dict
class FileItem(dict):
    def __init__(self, fname):
        self['fname'] = fname

    #fname property
    fname: str = property()
    @fname.getter
    def fname(self):
        return self['fname']

    @fname.setter
    def fname(self, value: str):
        self['fname'] = value

    #Repeat for other properties
Run Code Online (Sandbox Code Playgroud)

是的,如果您有很多属性,这有点啰嗦,但它是 JSONSerialized 并且它的行为就像一个对象,您可以将它提供给任何需要它的库json.dumps(obj)


Dan*_*ugh 5

这是我的 3 美分...
这演示了树状 python 对象的显式 json 序列化。
注意:如果您确实想要一些这样的代码,您可以使用扭曲的 FilePath类。

import json, sys, os

class File:
    def __init__(self, path):
        self.path = path

    def isdir(self):
        return os.path.isdir(self.path)

    def isfile(self):
        return os.path.isfile(self.path)

    def children(self):        
        return [File(os.path.join(self.path, f)) 
                for f in os.listdir(self.path)]

    def getsize(self):        
        return os.path.getsize(self.path)

    def getModificationTime(self):
        return os.path.getmtime(self.path)

def _default(o):
    d = {}
    d['path'] = o.path
    d['isFile'] = o.isfile()
    d['isDir'] = o.isdir()
    d['mtime'] = int(o.getModificationTime())
    d['size'] = o.getsize() if o.isfile() else 0
    if o.isdir(): d['children'] = o.children()
    return d

folder = os.path.abspath('.')
json.dump(File(folder), sys.stdout, default=_default)
Run Code Online (Sandbox Code Playgroud)


Los*_*der 5

这个类可以做到这一点,它将对象转换为标准的json.

import json


class Serializer(object):
    @staticmethod
    def serialize(object):
        return json.dumps(object, default=lambda o: o.__dict__.values()[0])
Run Code Online (Sandbox Code Playgroud)

用法:

Serializer.serialize(my_object)
Run Code Online (Sandbox Code Playgroud)

python2.7和工作python3.


Mar*_*oma 5

jaraco给出了一个非常简洁的答案。我需要修复一些小问题,但这有效:

代码

# Your custom class
class MyCustom(object):
    def __json__(self):
        return {
            'a': self.a,
            'b': self.b,
            '__python__': 'mymodule.submodule:MyCustom.from_json',
        }

    to_json = __json__  # supported by simplejson

    @classmethod
    def from_json(cls, json):
        obj = cls()
        obj.a = json['a']
        obj.b = json['b']
        return obj

# Dumping and loading
import simplejson

obj = MyCustom()
obj.a = 3
obj.b = 4

json = simplejson.dumps(obj, for_json=True)

# Two-step loading
obj2_dict = simplejson.loads(json)
obj2 = MyCustom.from_json(obj2_dict)

# Make sure we have the correct thing
assert isinstance(obj2, MyCustom)
assert obj2.__dict__ == obj.__dict__
Run Code Online (Sandbox Code Playgroud)

请注意,我们需要两个步骤来加载。目前,该__python__房产尚未使用。

这种情况有多常见?

使用AlJohri的方法,我检查了方法的受欢迎程度:

序列化(Python -> JSON):

反序列化(JSON -> Python):


归档时间:

查看次数:

606683 次

最近记录:

5 年,11 月 前