>>> 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>
>>>
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
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
例:
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)
def getSerializable(doc):
# check if it's a list
if isinstance(doc, list):
for i, val in enumerate(doc):
doc[i] = getSerializable(doc[i])
return doc
# check if it's a dict
if isinstance(doc, dict):
for key in doc.keys():
doc[key] = getSerializable(doc[key])
return doc
# Process ObjectId
if isinstance(doc, ObjectId):
doc = str(doc)
return doc
# Use any other custom serializting stuff here...
# For the rest of stuff
return doc
0
我选择使用装饰器来解决日期时间对象序列化问题 . 这是我的代码:
#myjson.py
#Author: jmooremcc 7/16/2017
import json
from datetime import datetime, date, time, timedelta
"""
This module uses decorators to serialize date objects using json
The filename is myjson.py
In another module you simply add the following import statement:
from myjson import json
json.dumps and json.dump will then correctly serialize datetime and date
objects
"""
def json_serial(obj):
"""JSON serializer for objects not serializable by default json code"""
if isinstance(obj, (datetime, date)):
serial = str(obj)
return serial
raise TypeError ("Type %s not serializable" % type(obj))
def FixDumps(fn):
def hook(obj):
return fn(obj, default=json_serial)
return hook
def FixDump(fn):
def hook(obj, fp):
return fn(obj,fp, default=json_serial)
return hook
json.dumps=FixDumps(json.dumps)
json.dump=FixDump(json.dump)
if __name__=="__main__":
today=datetime.now()
data={'atime':today, 'greet':'Hello'}
str=json.dumps(data)
print str
class Serializer(object):
@staticmethod
def serialize(obj):
def check(o):
for k, v in o.__dict__.items():
try:
_ = json.dumps(v)
o.__dict__[k] = v
except TypeError:
o.__dict__[k] = str(v)
return o
return json.dumps(check(obj).__dict__, indent=2)
22 回答
有很多方法可以解决这个问题 . 'ObjDict'(pip install objdict)是另一个 . 重点是提供类似javascript的对象,它们也可以像字典一样最好地处理从JSON加载的数据,但是还有其他功能也很有用 . 这为原始问题提供了另一种替代解决方案 .
您对预期产量有所了解吗?对于例如这会吗?
在这种情况下,您只能调用
json.dumps(f.__dict__)
.如果您想要更多自定义输出,那么您必须继承JSONEncoder并实现自己的自定义序列化 .
有关一个简单的例子,请参见下文 .
然后将此类作为
cls
kwarg传递给json.dumps()方法:如果您还想要解码,那么您必须为JSONDecoder类提供自定义
object_hook
. 对于例如这是一个简单的功能的简单解决方案:
.toJSON()方法
而不是JSON可序列化类,实现序列化方法:
所以你只需要将其命名为序列化:
将输出:
对于更复杂的类,您可以考虑使用工具jsonpickle:
(link to jsonpickle on PyPi)
大多数答案都涉及将调用更改为 json.dumps() ,这并不总是可行或可取的(例如,它可能发生在框架组件中) .
如果您希望能够按原样调用 json.dumps(obj) ,那么一个简单的解决方案将继承自 dict :
如果您的类只是基本数据表示,那么这种方法很有效,对于您可以始终明确设置键的棘手问题 .
另一种选择是将JSON转储包装在自己的类中:
或者,更好的是,从
JsonSerializable
类继承FileItem类:测试:
我喜欢Onur's answer但会扩展为包含一个可选的
toJSON()
方法,以便对象自行序列化:前几天我遇到了这个问题并实现了一个更通用的Python编译器版本,可以 handle nested objects 和 inherited fields :
例:
结果:
只需将
to_json
方法添加到您的类中,如下所示:并将此代码(从this answer)添加到所有内容的顶部:
这将在导入时对其进行猴子补丁json模块,以便JSONEncoder.default()自动检查特殊的“to_json()”方法,并使用它来编码对象(如果找到) .
就像Onur说的那样,但这次你不必更新项目中的每个
json.dumps()
.如果使用标准
json
,则需要定义default
函数json
在它可以打印的对象方面是有限的,并且jsonpickle
(你可能需要一个pip install jsonpickle
)是有限的,它可以改变,我仍然找不到比以下更直的方式:注意,仍然无法打印对象方法 .
这个类可以做到这一点,它将对象转换为标准的json .
用法:
在
python2.7
和python3
工作 .jaraco给出了一个非常巧妙的答案 . 我需要解决一些小问题,但这有效:
代码
请注意,我们需要两个加载步骤 . 目前,未使用
__python__
属性 .这有多常见?
使用AlJohri的方法,我检查方法的流行度:
序列化(Python - > JSON):
to_json:266,595于2018-06-27
2018-06-27
toJSON:96,307
json:2018-06-27 8,504
for_json:2018-06-27 6,937
反序列化(JSON - > Python):
2018-06-27
jsonweb对我来说似乎是最好的解决方案 . 见http://www.jsonweb.info/en/latest/
这是我的3美分......
这演示了树状python对象的显式json序列化 .
注意:如果你真的想要这样的代码,你可以使用twisted FilePath类 .
如果您不介意为它安装软件包,可以使用json-tricks:
之后你只需要从
json_tricks
而不是json导入dump(s)
,它通常会起作用:哪个会给
这基本上就是它!
这一般都会很好用 . 有一些例外,例如如果特殊事情发生在
__new__
,或者更多的元类魔法正在发生 .显然加载也有效(否则有什么意义):
这确实假设
module_name.test_class.MyTestCls
可以导入并且没有以不兼容的方式更改 . You'll get back an instance ,不是一些字典或其他东西,它应该与您倾销的副本完全相同 .如果要自定义(de)序列化的方式,可以向类中添加特殊方法,如下所示:
例如,它仅序列化部分属性参数 .
作为一个免费的奖金,你得到(de)numpy数组的序列化,日期和时间,有序 Map ,以及在json中包含注释的能力 .
免责声明:我创建了json_tricks,因为我遇到了和你一样的问题 .
当我试图将Peewee的模型存储到PostgreSQL _691965中时,我遇到了这个问题 .
经过一段时间的努力,这是一般的解决方案 .
我的解决方案的关键是通过Python的源代码,并意识到代码文档(描述here)已经解释了如何扩展现有的
json.dumps
以支持其他数据类型 .假设您当前的模型包含一些不可序列化为JSON的字段,并且包含JSON字段的模型最初如下所示:
只需像这样定义一个自定义
JSONEncoder
:然后在你的
JSONField
中使用它,如下所示:关键是上面的
default(self, obj)
方法 . 对于从Python收到的每一个... is not JSON serializable
投诉,只需添加代码来处理unserializable-to-JSON类型(例如Enum
或datetime
)例如,这是我如何支持从
Enum
继承的类:最后,使用上面实现的代码,您可以将任何Peewee模型转换为JSON可加密对象,如下所示:
虽然上面的代码(有点)特定于Peewee,但我认为:
一般适用于其他ORM(Django等)
此外,如果您了解
json.dumps
如何工作,此解决方案也适用于Python(也称为ORM)有任何问题,请在评论部分发布 . 谢谢!
这是一个小型库,它将一个对象及其所有子节点序列化为JSON,并将其解析回来:
https://github.com/Toubs/PyJSONSerialization/
我提出了自己的解决方案 . 使用此方法,传递任何文档(dict,list,ObjectId等)以进行序列化 .
我选择使用装饰器来解决日期时间对象序列化问题 . 这是我的代码:
通过导入上面的模块,我的其他模块以正常方式使用json(不指定default关键字)来序列化包含日期时间对象的数据 . json.dumps和json.dump会自动调用datetime序列化程序代码 .
我最喜欢Lost Koder的方法 . 当尝试序列化更复杂的对象时,我遇到了问题,其中成员/方法不可序列化 . 这是我的实现,适用于更多对象: