我有这种格式的字符串,
d = {'details': {'hawk_branch': {'tandem': ['4210bnd72']}, 'uclif_branch': {'tandem': ['e2nc712nma89', '23s24212', '12338cm82']}}}
我想以这种格式将其写入文件,将列表转换为字典,并为列表中的每个值添加单词value
作为键,
因此{'tandem': ['4210bnd72']}
应该变成
"tandem": {
"value": "4210bnd72"
}
这是预期的输出文件,
{
"details": {
"hawk_branch": {
"tandem": {
"value": "4210bnd72"
}
},
"uclif_branch": {
"tandem": {
"value": "e2nc712nma89",
"value": "23s24212",
"value": "12338cm82",
}
}
}
}
我问了一个问题here,有人回答使用json.JSONEncoder
,
class restore_value(json.JSONEncoder):
def encode(self, o):
if isinstance(o, dict):
return '{%s}' % ', '.join(': '.join((json.encoder.py_encode_basestring(k), self.encode(v))) for k, v in o.items())
if isinstance(o, list):
return '{%s}' % ', '.join('"value": %s' % self.encode(v) for v in o)
return super().encode(o)
使用上述编码器,如果输入为
d = {'details': {'hawk_branch': {'tandem': ['4210bnd72']}, 'uclif_branch': {'tandem': ['e2nc712nma89', '23s24212', '12338cm82']}}}
输出将变为
print(json.dumps(d, cls=restore_value))
{"details": {"hawk_branch": {"tandem": {"value": "4210bnd72"}}, "uclif_branch": {"tandem": {"value": "e2nc712nma89", "value": "23s24212", "value": "12338cm82"}}}}
这正是我想要的,但是现在我想将其写入文件。
with open("a.json", "w") as f:
json.dump(d, f, cls=restore_value)
但是它的写入方式与json.dumps
的输出方式不同。
预期输出
{"details": {"hawk_branch": {"tandem": {"value": "4210bnd72"}}, "uclif_branch": {"tandem": {"value": "e2nc712nma89", "value": "23s24212", "value": "12338cm82"}}}}
我得到的输出
{"details": {"hawk_branch": {"tandem": ["4210bnd72"]}, "uclif_branch": {"tandem": ["e2nc712nma89", "23s24212", "12338cm82"]}}}
有人可以告诉我,即使我使用编码器,为什么写入文件的方式也不同?
复制
使用python 3复制并运行它,
import json
class restore_value(json.JSONEncoder):
def encode(self, o):
if isinstance(o, dict):
return '{%s}' % ', '.join(': '.join((json.encoder.py_encode_basestring(k), self.encode(v))) for k, v in o.items())
if isinstance(o, list):
return '{%s}' % ', '.join('"value": %s' % self.encode(v) for v in o)
return super().encode(o)
d = {'details': {'hawk_branch': {'tandem': ['4210bnd72']}, 'uclif_branch': {'tandem': ['e2nc712nma89', '23s24212', '12338cm82']}}}
print(json.dumps(d, cls=restore_value))
with open("a.json", "w") as f:
json.dump(d, f, cls=restore_value)
答案 0 :(得分:3)
原因在这里:
如果您在github上的json.__init__.py
中查看CPython/Lib/json
的源代码:https://github.com/python/cpython/blob/master/Lib/json/init.py
您会发现json.dump
实际使用:
if (not skipkeys and ensure_ascii and
check_circular and allow_nan and
cls is None and indent is None and separators is None and
default is None and not sort_keys and not kw):
iterable = _default_encoder.iterencode(obj)
else:
if cls is None:
cls = JSONEncoder
iterable = cls(skipkeys=skipkeys, ensure_ascii=ensure_ascii,
check_circular=check_circular, allow_nan=allow_nan, indent=indent,
separators=separators,
default=default, sort_keys=sort_keys, **kw).iterencode(obj)
# could accelerate with writelines in some versions of Python, at
# a debuggability cost
for chunk in iterable:
fp.write(chunk)
因此,您想override
使用的功能应该是json.JSONEncoder.iterencode
而不是encode
。
答案 1 :(得分:1)
json.dumps
的 cls
将在您的JSON对象上调用encode
方法,该方法将返回字符串表示形式。另一方面,json.dump
将调用您尚未实现的default
方法。来自json.dump
文档:
要使用自定义JSONEncoder子类(例如,一个覆盖default()方法以序列化其他类型的子类),请使用cls kwarg指定它;否则将使用JSONEncoder。
因此,json.dump
使用默认的default
方法,该方法不会影响您的原始对象并将其写入。
以所需方式写入文件的最简单方法是
with open("a.json", "w") as f:
f.write(json.dumps(d, cls=restore_value))