【问题标题】:formatting JSON with a dict用 dict 格式化 JSON
【发布时间】:2021-12-28 22:53:59
【问题描述】:

我正在为技术用户编写一些代码,以便在 JSON 中传递变量的占位符,并附带一个定义每个变量的字典。我想用这些值替换这些变量,最终需要将其放入 Python 字典中。想象一下,我从这个开始:

>>> json_in = """
{
    "sidebar": {
        "type": "sidebar",
        "title": "<h1>Vulnerability Data</h1>",
        "description": {md_html}
    },
    "widgets": [
        {
            "name": "Map",
            "itemId": {item_id},
            "showNavigation": false
        }
    ]
}"""
>>> args = {'md_html': '<super_long_html_string>', 'item_id': 'abcdef12345'}

如果我尝试使用json_in.format(**args) 之类的格式,我只会在遇到第一个左大括号(“侧边栏”之前)时收到 KeyError,该格式会尝试读取。将花括号加倍会在format() 中转义它们,但是这个 JSON 可能有数千行长,所以我真的不想让人们做大量的重新格式化。我想我可以尝试在format() 之前使用 Python 编辑 JSON。我必须避免从格式化字符串中破坏花括号,所以这似乎变得不必要的复杂。 Python通常有简单的解决方案,那我错过了什么?


我走的另一条路是首先将其创建为 Python dict。很容易搜索 JSONisms 并替换为 Python 等效项(例如:falseFalsetrueTrue)。我没有格式化字符串 ({item_id}),而是使用变量 (item_id) 来结束这样的事情:

>>> md_html = '<super_long_html_string>'
>>> item_id = 'abcdef12345'
>>> dict_in = {
    "sidebar": {
        "type": "sidebar",
        "title": "<h1>Vulnerability Data</h1>",
        "description": md_html
    },
    "widgets": [
        {
            "name": "Map",
            "itemId": item_id,
            "showNavigation": False
        }
    ]
}

问题是变量md_htmlitem_id 在这个例子中是硬编码的,我想接受用户传入的任何内容(参见上面的args dict)。如果我可以创建一个带有占位符的字典并用提供的输入替换它们,那将解决我的问题。

【问题讨论】:

标签: python json dictionary format


【解决方案1】:

我会使用jq library 来定义这样一个 JSON 模板。

import jq


json_in = """
{
    "sidebar": {
        "type": "sidebar",
        "title": "<h1>Vulnerability Data</h1>",
        "description": $md_html
    },
    "widgets": [
        {
            "name": "Map",
            "itemId": $item_id,
            "showNavigation": false
        }
    ]
}"""


args = {'md_html': '<super_long_html_string>', 'item_id': 'abcdef12345'}

result = jq.compile(json_in, args=args).input("")

【讨论】:

  • 看起来像这样和模板字符串(见上文)都可以解决问题,但我接受了这个作为答案,因为它也验证了 JSON。我最初并不太担心验证 JSON,因为用户从它开始是有效的。但是我什至无法在不搞砸的情况下输入这个问题(我的变量周围缺少引号),所以很明显验证很有用!
【解决方案2】:

如果您可以控制json_in,请查看Template Strings

from string import Template
json_in = """
{
    "sidebar": {
        "type": "sidebar",
        "title": "<h1>Vulnerability Data</h1>",
        "description": $md_html
    },
    "widgets": [
        {
            "name": "Map",
            "itemId": $item_id,
            "showNavigation": false
        }
    ]
}"""
args = {'md_html': '<super_long_html_string>', 'item_id': 'abcdef12345'}
Template(json_in).substitute(args)

输出

{
    "sidebar": {
        "type": "sidebar",
        "title": "<h1>Vulnerability Data</h1>",
        "description": <super_long_html_string>
    },
    "widgets": [
        {
            "name": "Map",
            "itemId": abcdef12345,
            "showNavigation": false
        }
    ]
}

我想你会想要在字符串周围加上引号,我只是让 json 尽可能接近你的问题。

【讨论】:

  • Template 不会确保结果是有效的 JSON,如果您在替换之前不清理参数值,这可能会导致严重问题。
  • 谢谢,这是一个很好的答案。我接受了下面的jq 答案,因为这包括验证,但这基本上做同样的事情。我喜欢的是它不需要任何额外的库。
猜你喜欢
  • 1970-01-01
  • 2021-07-25
  • 2022-01-01
  • 2018-01-30
  • 2018-01-25
  • 1970-01-01
  • 1970-01-01
  • 2016-05-03
  • 1970-01-01
相关资源
最近更新 更多