Home > Net >  formatting JSON with a dict
formatting JSON with a dict

Time:12-29

I am writing some code for technical users to pass in JSON with placeholders for variables, accompanied by a dict to define each of those variables. I want to replace those variables with the values and ultimately need to get it into a Python dict. Imagine I start with this:

>>> 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'}

If I try to do a format like json_in.format(**args), I just get a KeyError when it hits the first opening curly brace (before "sidebar"), which format tries to read. Doubling the curly braces escapes them in format(), but this JSON can be thousands of lines long, so it's really not something I want to make people do a ton of reformatting on. I guess I can try to edit the JSON with Python before the format(). I'd have to avoid mangling the curly braces from the formatting strings, so this seems like it's getting needlessly complex. Python usually has simple solutions, so what am I missing?


Another path I went down is just to create it as a Python dict in the first place. It's easy to search for JSONisms and replace with the Python equivalents (e.g.: false to False, true to True). Instead of formatting strings ({item_id}), I just use variables (item_id) to end up with something like this:

>>> 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
        }
    ]
}

The problem is that the variables md_html and item_id are hard-coded in this example, and I want to accept whatever the user passes in (see the args dict above). If I could create a dict with placeholders and replace them with inputs supplied, that would solve my problem.

CodePudding user response:

I would use the jq library to define such a JSON template.

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("")

CodePudding user response:

Check out Template Strings if you have control over json_in.

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)

Output

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

I suppose you'll want quotes around the strings, I just left the json as close to your question as possible.

  • Related