【问题标题】:String format a JSON string gives KeyError字符串格式 JSON 字符串给出 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"'

【问题讨论】:

    标签: python json string format


    【解决方案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 回答和评论:

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

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

    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)
    

    【讨论】:

    【解决方案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 {..} 不是占位符的对。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-12
    • 2021-09-25
    • 2019-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多