json.dumps()默认不支持set/frozenset,需通过default参数或自定义JSONEncoder处理;default最轻量,但需注意无序性、无限循环及嵌套未处理问题。
js
on.dumps() 默认不支持 set / frozenset
直接传
或
给
会报
。JSON 标准本身没有对应集合的类型,Python 的
模块默认只认
、
、
、
、
、
和
。
用 default 参数把 set 转成 list
最常用、最轻量的做法是通过
参数提供一个
回调函数
,对不认识的类型做转换:
函数只在遇到无法序列化的对象时被调用,不影响其他类型
返回
是安全的,但注意:
无序,转成
后顺序不保证(如需稳定顺序,可加
)
不要在
中返回原始
或递归调用
,否则会无限循环
需要保持集合语义?考虑自定义 encoder 类
如果下游解析器能配合改造,想显式区分“这是个集合”,可以继承
并重写
或
:
这种格式增加了元信息,但要求解析端也识别
字段并还原
不能和
参数混用(
优先级更高)
若数据里还有其他自定义类型,记得在
末尾调用
,否则会丢弃默认行为
注意嵌套结构和不可哈希元素
里如果包含不可 JSON 序列化的对象(比如另一个
、函数、或自定义类实例),仅靠上面的
还不够:
会失败,因为内层
在外层
时才触发序列化,但此时已脱离
控制范围
正确做法是确保
能递归处理——但
不提供递归钩子,所以得手动扁平化或预处理
更稳妥的方式是:在调用
前,用
递归函数
把所有
/
替换为
,再 dump
真正容易被忽略的是:你以为只改了顶层
就万事大吉,结果数据嵌套三层后某个字典的值仍是未处理的
,错误才冒出来。
setfrozensetjson.dumps()TypeError: Object of type set is not JSON serializablejsondictliststrintfloatboolNonedefaultimport json
def json_default(obj):
if isinstance(obj, (set, frozenset)):
return list(obj)
raise TypeError(f"Object of type {type(obj).name} is not JSON serializable")
data = {"tags": {"python", "web", "api"}, "readonly": frozenset([1, 2, 3])}
json_str = json.dumps(data, default=json_default, sort_keys=True)
→ {"readonly": [1, 2, 3], "tags": ["api", "python", "web"]}
defaultlist(obj)setlistsorted()defaultobjjson.dumps()json.JSONEncoderencodedefaultclass SetEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, set):
return {"__set__": True, "values": list(obj)}
if isinstance(obj, frozenset):
return {"__frozenset__": True, "values": list(obj)}
return super().default(obj)
json.dumps({"s": {1, 2}}, cls=SetEncoder)
php版微信js-sdk支付接口类
php版微信js-sdk支付接口类
下载
→ {"s": {"set": true, "values": [1, 2]}}
__set__defaultclsdefaultsuper().default(obj)setsetdefault{1, {2, 3}}setlist(obj)defaultdefaultjson.dumps()json.dumps()setfrozensetlistsetfrozenset