自定义数据类型(如datetime)序列化到/从json。
jsonplus的Python项目详细描述
将python类型序列化为“工作正常”的json。
忘记以下错误:
TypeError: datetime.datetime(...) is not JSON serializable
除了基本类型的(反)序列化(由simplejson)之外,jsonplus 提供对其他常用类型的exact(de-)序列化的支持,例如: tuple/namedtuple,set/frozenset,complex/decimal.Decimal/fractions.Fraction, 以及datetime/date/time/timedelta。
如果类型的确切表示不是你的茶,并且你所希望的 for是使用非基本类型处理数据结构的json.dumps, 接受一路上“类型精度”的损失,就可以使用 兼容性模式(线程本地jsonplus.prefer_compat(),或 每次调用重写jsonplus.dumps(..., exact=False))。
安装
jsonplus作为python包提供。要安装它,只需键入:
$ pip install jsonplus
用法
您可以将jsonplus视为一个友好的drop in替换json/simplejson。
>>>importjsonplusasjson>>>x=json.loads('{"a":1,"b":2}')>>>y=json.dumps(x,indent=4)>>>z=json.pretty(x)
示例
让我们从心爱的datetime开始。
>>>importjsonplusasjson>>>fromdatetimeimportdatetime>>>json.dumps({..."x":[4,3],..."t":datetime.now()...})'{"x":[4,3],"t":{"__class__":"datetime","__value__":"2013-09-06T23:38:55.819791"}}'>>>json.loads(_){u'x':[4,3],u't':datetime.datetime(2013,9,6,23,38,55,819791)}
类似于其他类型的datetime.*,如timedelta、date和time:
>>>fromdatetimeimporttimedelta,date,time>>>print(json.pretty({"dt":timedelta(0,1234567,123),"d":date.today(),"t":datetime.now().time()})){"d":{"__class__":"date","__value__":"2013-09-22"},"dt":{"__class__":"timedelta","__value__":{"days":14,"microseconds":123,"seconds":24967}},"t":{"__class__":"time","__value__":"23:33:16.335360"}}
另外,set和complex:
>>>json.dumps([set(range(3)),1+2j])'[{"__class__":"set","__value__":[0,1,2]},{"__class__":"complex","__value__":{"real":1.0,"imag":2.0}}]'>>>json.loads(_)[set([0,1,2]),(1+2j)]
tuple和namedtuple也被保留:
>>>fromcollectionsimportnamedtuple>>>Point=namedtuple('Point',['x','y'])>>>data=json.pretty({"vect":(1,2,3),"dot":Point(3,4)})>>>print(data){"dot":{"__class__":"namedtuple","__value__":{"fields":["x","y"],"name":"Point","values":[3,4]}},"vect":{"__class__":"tuple","__value__":[1,2,3]}}>>>json.loads(data){'vect':(1,2,3),'dot':Point(x=3,y=4)}
兼容模式
完全模式下支持的所有类型在兼容性中也受支持 模式。但是,json表示方式不同。
在精确模式下,type和value用JSON Object编码 __class__和__value__键,在兼容模式下, 值被“舍入”为最接近的json类型。
例如,tuple和set用JSON Array表示,并且 namedtuple被编码为纯JSON Object。Decimal是 表示为JSON Number,具有任意精度(如果 解码为float)。
要在exact和compatibility模式之间切换,请使用 (线程本地)函数prefer_exact()和prefer_compat(),或调用 dumps(..., exact=False):
>>>importjsonplusasjson>>>json.prefer_compat()# or:>>>json.prefer(json.COMPAT)# per-instance override:>>>json.dumps(obj,exact=False)# to go back to (default) exact coding:>>>json.prefer_exact()
上面的tuple/namedtuple/datetime示例在兼容性中运行 编码模式结果:
>>>json.prefer_compat()>>>print(json.pretty({"vect":(1,2,3),"dot":Point(3,4)})){"point":{"x":3,"y":4},"vector":[1,2,3]}>>>json.dumps({"now":datetime.now()})'{"now":"2017-01-26T00:37:40.293963"}'
因此,为了能够在兼容模式下正确解码值,有些 必须向解码器提供额外的上下文。
添加用户类型
通过@jsonplus.encoder和 @jsonplus.decoder装饰器。
例如,要在精确模式下启用名为mytype的类型的序列化 (要添加compat模式序列化,请在decorator中附加exact=False:
@jsonplus.encoder('mytype')defmytype_exact_encoder(myobj):returnmyobj.to_json()
@jsonplus.decoder('mytype')defmytype_decoder(value):returnmytype(value,reconstruct=True,...)
如果对象类的检测比简单的类名比较复杂, 如果需要使用谓词函数,只需将predicate=...添加到encoder 装饰工。例如:
@jsonplus.encoder('BaseClass',lambdaobj:isinstance(obj,BaseClass))defall_derived_classes_encoder(derived):returnderived.base_encoder()