字符串格式 JSON 字符串给出 KeyError

Posted

技术标签:

【中文标题】字符串格式 JSON 字符串给出 KeyError【英文标题】:String format a JSON string gives KeyError 【发布时间】:2013-04-27 17:35:39 【问题描述】:

为什么这段代码会给出KeyError

output_format = """
 
    "File": "filename", 
    "Success": success, 
    "ErrorMessage": "error_msg", 
    "LogIdentifier": "log_identifier" 

"""

print output_format.format(filename='My_file_name',
                           success=True,
                           error_msg='',
                           log_identifier='123')

错误信息:

KeyError: ' "File"'

【问题讨论】:

【参考方案1】:

正如 Tudor 在 comment 中提到的另一个答案,Template 类是最适合我的解决方案。我正在处理嵌套字典或字典列表,并且处理它们并不那么简单。

虽然解决方案很简单,但使用模板。

我从一个转换成字符串的字典开始。然后,我将所有 实例替换为 $,这是用于替换占位符的模板标识符。

让它工作的关键是使用模板方法safe_substitute。它将替换所有有效的占位符,如$user_id,但忽略任何属于字典结构的无效占位符,如$'name': 'John', ...

替换完成后,我删除所有剩余的 $ 并将字符串转换回字典。

在下面的代码中,resolve_placeholders 返回一个字典,其中每个键都与有效负载字符串中的占位符匹配,值被模板类替换。

from string import Template
.
.
.
payload = json.dumps(payload)
payload = payload.replace('', '$')
replace_values = self.resolve_placeholders(payload)
if replace_values:
    string_template = Template(payload)
    payload = string_template.safe_substitute(replace_values)
payload = payload.replace('$', '')
payload = json.loads(payload)

【讨论】:

我使用了这种方法,因为它在使用 RegEx 后非常优雅,并且使用了一个否定的lookbehind 允许我的 JSON 模板仍然使用$ 来清楚地指示模板标签。所以你的payload.replace( ... ) 变成re.sub(r"(?<!\$)()", '$', payload) 只替换 并忽略所有出现的$。最后一步对于.replace( ...) 来说是可以的,但为了完整起见,我使用了re.sub(r"(\$\)", '', payload)【参考方案2】:

继续Martijn Pieters 回答和评论:

    根据 MA​​rtijn 的评论,转义不是占位符的 .. 对是使用嵌套字典的方式。我没有成功,所以我建议以下方法。

    对于嵌套字典,我尝试在嵌套字典的任何 和 上加倍。

a='"names":"a":"name"'

a.format(name=123) 输出:

输出:'"names":"a":"123"'

但这使得使用 format 来更改 json 字符串中的值,这是一种过于复杂的方法,所以我对 format 命令使用了一个扭曲。 我将 $param_name 替换为 json 字符串。例如:

我的预定义 JSON 如下所示:

my_json_dict = 
     'parameter': [
         
             'name': 'product',
             'value': '$product'
         ,
         
             'name': 'suites',
             'value': '$suites'
         ,
         
             'name': 'markers',
             'value': '$markers'
         
     ]
 

我将这个字典作为要替换的值而不是参数提供

parameters = 
    'product': 'spam',
    'suites': 'ham',
    'markers': 'eggs'

并使用此代码进行替换

json_str = json.dumps(my_json_dict)
for parameter_name, parameter_value in parameters.iteritems():
        parameter_name = '$'+parameter_name+''
        json_str = json_str.replace(parameter_name, parameter_value)

json_dict = json.loads(json_str)

【讨论】:

也许string.Template 可能会有所帮助。【参考方案3】:

你需要把外大括号加倍;否则 Python 认为 "File".. 也是一个参考:

output_format = ' "File": "filename", "Success": success, "ErrorMessage": "error_msg", "LogIdentifier": "log_identifier" '

结果:

>>> print output_format.format(filename='My_file_name',
...                            success=True,
...                            error_msg='',
...                            log_identifier='123')
 "File": "My_file_name", "Success": True, "ErrorMessage": "", "LogIdentifier": "123" 

如果您正在生成 JSON 输出,最好使用 json module:

>>> import json
>>> print json.dumps('File': 'My_file_name',
...                   'Success': True,
...                   'ErrorMessage': '',
...                   'LogIdentifier': '123')
"LogIdentifier": "123", "ErrorMessage": "", "Success": true, "File": "My_file_name"

注意输出中的小写 true,这是 JSON 标准所要求的。

【讨论】:

如果我能给这个答案 10 票,我会的。谢谢 为了清楚起见,我将添加此评论作为答案。请注意,对于嵌套字典,您需要在嵌套字典的任何 和 上加倍。 @RaamEE:你需要转义 all .. 不是占位符的对。

以上是关于字符串格式 JSON 字符串给出 KeyError的主要内容,如果未能解决你的问题,请参考以下文章

在 Python 中格式化字符串和命名参数

Pandas json_normalize 返回 KeyError

迭代JSON给出字符,而不是元素

在 keras 中绘制曲线给出 KeyError: 'accuracy'

为啥 str(KeyError) 添加额外的引号?

XGBoost 提前停止给出 KeyError: 'best_msg'