Форматировать какой-нибудь объект JSON с определенными полями в одну строку? - PullRequest
0 голосов
/ 06 ноября 2019

Я хочу переформатировать файл JSON таким образом, чтобы определенные объекты (словари) с определенными ключами находились в одной строке.

Например, любой объект с ключом name должен отображаться в одной строке:

{
  "this": "that",
  "parameters": [
    { "name": "param1", "type": "string" },
    { "name": "param2" },
    { "name": "param3", "default": "@someValue" }
  ]
}

Файл JSON создан и содержит данные о языке программирования. Однострочные определенные поля значительно упрощают визуальный осмотр / просмотр.

Я пытался переопределить python json.JSONEncoder, чтобы превратить соответствующий dict в string перед записью, только для реализации кавычек "внутри строки снова выводятся в результирующем JSON-файле, опровергая мою цель.

Я тоже посмотрел на jq, но не смог придумать, как это сделать. Я нашел похожие вопросы и решения, основанные на длине строки, но мои требования проще, и я не хочу, чтобы другие более короткие строки были изменены. Только определенные объекты или поля.

1 Ответ

2 голосов
/ 06 ноября 2019

Этот код рекурсивно заменяет все соответствующие данные в данных уникальными строками (UUID) и записывает эти замены, затем в строке JSON с отступом уникальные строки заменяются желаемой исходной однострочной JSON.

replace возвращает пару:

  • Модифицированная версия данных входного аргумента
  • Список пар строк JSON, где для каждой пары первое значение должно быть заменено навторое значение в финале довольно напечатано JSON.
import json
import uuid


def replace(o):
    if isinstance(o, dict):
        if "name" in o:
            replacement = uuid.uuid4().hex
            return replacement, [(f'"{replacement}"', json.dumps(o))]
        replacements = []
        result = {}
        for key, value in o.items():
            new_value, value_replacements = replace(value)
            result[key] = new_value
            replacements.extend(value_replacements)
        return result, replacements
    elif isinstance(o, list):
        replacements = []
        result = []
        for value in o:
            new_value, value_replacements = replace(value)
            result.append(new_value)
            replacements.extend(value_replacements)
        return result, replacements
    else:
        return o, []


def pretty(data):
    data, replacements = replace(data)
    result = json.dumps(data, indent=4)
    for old, new in replacements:
        result = result.replace(old, new)
    return result


print(pretty({
    "this": "that",
    "parameters": [
        {"name": "param1", "type": "string"},
        {"name": "param2"},
        {"name": "param3", "default": "@someValue"}
    ]
}))

...