[英]Unable to format Python string while decoding from dict to str
我有一个字典,我编码为这样的字符串:
import json
template = json.dumps({
'_index': '{0}',
'_type': '{1}',
'_id': '{2}',
'_source': {
'doc': '{3}',
'doc_as_upsert': True
}
})
现在,我尝试按照此处提到的新python约定对其进行格式化: https : //pyformat.info/
print template.format('one','two','three','four')
但是,我得到一个错误
追溯(最近一次呼叫最近):文件“ python”,第1行,KeyError:““ _ type”'
我在这里做错了什么?
问题源于JSON中的花括号-您需要对其进行两次转义才能使str.format()
起作用,例如:
import json
template = json.dumps({
'_index': '{0}',
'_type': '{1}',
'_id': '{2}',
'_source': {
'doc': '{3}',
'doc_as_upsert': True
}
})
template = template.replace("{", "{{").replace("}", "}}")
print(template.format('one','two','three','four'))
它将不再出错,但也将转义您的参数大括号,以便它们不会被str.format()
取代,因此,您还必须发明自己的“参数”转义str.format()
确保它不会出现)作为JSON的标记代码,就像花括号一样),例如使用<
和>
代替:
import json
template = json.dumps({
'_index': '<0>',
'_type': '<1>',
'_id': '<2>',
'_source': {
'doc': '<3>',
'doc_as_upsert': True
}
})
template = template.replace("{", "{{").replace("}", "}}").replace("<", "{").replace(">", "}")
print(template.format('one', 'two', 'three', 'four'))
但是,最好是在将数据转换为JSON之前直接替换数据。 您可以分别对dict
每个( str
) value
调用str.format()
,将包含所有参数的dict
传递给它,并使用命名参数(即{one}
)从扩展键中获取所需的参数。
更新 :您甚至不需要对最后一个数据进行递归,因为json
序列化器无论如何都要对它进行递归,但是不幸的是, json
模块并不便于交换字符串序列化的默认行为,因此您必须进行一些猴子修补:
from json import dumps, encoder
def template_json(data, args, **kwargs):
json_s1, json_s2 = encoder.encode_basestring, encoder.encode_basestring_ascii
encoder.encode_basestring = lambda s: json_s1(s.format(**args))
encoder.encode_basestring_ascii = lambda s: json_s2(s.format(**args))
try:
return dumps(data, **kwargs)
finally:
encoder.encode_basestring, encoder.encode_basestring_ascii = json_s1, json_s2
它本质上是暂时将内部JSON字符串构建方法与首先应用格式的方法一起包装,然后还原所有内容,以便可能依赖json
模块的其他函数不会出现意外行为(尽管这里也存在一些危险-这不是线程安全的)。 由于它将一一读取元素,因此我们不能真正使用位置格式,因此如上所述使用命名格式。 您可以将其测试为:
data = {
'_index': '{one}',
'_type': '{two}',
'_id': '{three}',
'_source': {
'doc': '{four}',
'doc_as_upsert': True,
}
}
template_vars = {"one": "value 1", "two": "value 2", "three": "value 3", "four": "value 4"}
print(template_json(data, template_vars, indent=4))
导致:
{
"_source": {
"doc": "value 4",
"doc_as_upsert": true
},
"_index": "value 1",
"_id": "value 3",
"_type": "value 2"
}
但是,通常来说,如果您必须四处乱搞才能实现所需的功能-您可能首先要重新考虑这是否是正确的方法,并且可以以更简单的方式实现目标吗?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.