【问题标题】:Edit dict recursively in Python在 Python 中递归编辑 dict
【发布时间】:2023-03-11 15:06:02
【问题描述】:

我有这样的字典

{
  "library": [
    {
      "_type": "Host",
      "parameters": "JSON STRING",
      "superclassOf": [
        {
          "_type": "LinuxHost",
          "superclassOf": [
            {
              "_type": "Ubuntu",
              "superclassOf": [
                {
                  "_type": "Ubuntu1604",
                  "parameters": "JSON STRING"
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

其中JSON STRING 是字符串形式的字典(例如'{"property1":"value1","property2":"value2"}')。 我正在寻找的是一种递归导航supeclassOf属性并将这些Json字符串转换为json的真实部分,并在编辑后返回完整字典的方法。

编辑:注意supeclassOf 的值是列表。所以到处都有superclassOf 可以有多个元素,每个元素都有(或没有)属性parameterssuperclassOf

EDIT2 使用 Prem Anand 的回答我收到此错误:

Traceback (most recent call last):
  File "C:/Users/ceccolig/PycharmProjects/api/api.py", line 61, in <module>
    main()
  File "C:/Users/ceccolig/PycharmProjects/api/api.py", line 52, in main
    process_list_or_dict(library)
  File "C:/Users/ceccolig/PycharmProjects/api/api.py", line 45, in process_list_or_dict
    process_list_or_dict(v)
  File "C:/Users/ceccolig/PycharmProjects/api/api.py", line 45, in process_list_or_dict
    process_list_or_dict(v)
  File "C:/Users/ceccolig/PycharmProjects/api/api.py", line 45, in process_list_or_dict
    process_list_or_dict(v)
  [Previous line repeated 5 more times]
  File "C:/Users/ceccolig/PycharmProjects/api/api.py", line 43, in process_list_or_dict
    ld[k] = process_str(v)
  File "C:/Users/ceccolig/PycharmProjects/api/api.py", line 37, in process_str
    return json.loads(s)
  File "C:\Users\ceccolig\AppData\Local\Programs\Python\Python38-32\lib\json\__init__.py", line 357, in loads
    return _default_decoder.decode(s)
  File "C:\Users\ceccolig\AppData\Local\Programs\Python\Python38-32\lib\json\decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "C:\Users\ceccolig\AppData\Local\Programs\Python\Python38-32\lib\json\decoder.py", line 353, in raw_decode
    obj, end = self.scan_once(s, idx)
json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)

【问题讨论】:

  • 到目前为止你有什么尝试?你能添加一些你试过但没有用的代码吗?
  • "将这些 Json 字符串转换为 json 的实数部分" 是什么意思?
  • @HichamZouarhi 我真的不知道从哪里开始......
  • @MisterNox 我的意思是我可以访问这些密钥。如果是字符串,则无法完成
  • 好吧,您可以将 json 数据转换为列表/字典,因此访问它们非常简单,但给我一个场景。如果我访问它们该怎么办?那我可以给你举个例子

标签: python json


【解决方案1】:

您可以使用json.loads 将json字符串转换为dict。浏览 dict 的每个元素,检查它的类型是 dict 还是 list 或 string 并相应地处理每种类型

import json

def process_str(s):
    if s and s[0]=='{' and s[-1]=='}':
        return json.loads(s)
    return s

def process_list_or_dict(ld):
    for k,v in enumerate(ld) if isinstance(ld, list) else ld.items():
        if isinstance(v, str):
            ld[k] = process_str(v)
        elif isinstance(v, (list, dict)):
            process_list_or_dict(v)

示例

dct = {'library': [{'_type': 'Host', 'parameters': '{"property1":"value1","property2":"value2"}', 'superclassOf': [{'_type': 'LinuxHost', 'superclassOf': [{'_type': 'Ubuntu', 'superclassOf': [{'_type': 'Ubuntu1604', 'parameters': '{"property3":"value3","property4":"value4"}'}]}]}]}]}

process_list_or_dict(dct)

print(json.dumps(dct, indent=4))

输出

{
    "library": [
        {
            "_type": "Host",
            "parameters": {
                "property1": "value1",
                "property2": "value2"
            },
            "superclassOf": [
                {
                    "_type": "LinuxHost",
                    "superclassOf": [
                        {
                            "_type": "Ubuntu",
                            "superclassOf": [
                                {
                                    "_type": "Ubuntu1604",
                                    "parameters": {
                                        "property3": "value3",
                                        "property4": "value4"
                                    }
                                }
                            ]
                        }
                    ]
                }
            ]
        }
    ]
}

【讨论】:

  • 感谢您的回答,但出现错误。检查我的问题编辑
  • 在我的问题中检查 EDIT2
  • 您的错误意味着您使用的 JSON_STRING 不是有效的 json 字符串。单个单词是否用双引号括起来,如示例字符串'{"property1":"value1","property2":"value2"}'
  • 是的,我错过了一个错误的字符串。但现在它给了我这个:if s[0]=='{' and s[-1]=='}': IndexError: string index out of range
  • 刚刚更新了我的答案,将if s[0]=='{' and s[-1]=='}': 替换为if s and s[0]=='{' and s[-1]=='}':。那应该可以解决它。
【解决方案2】:

好的,现在我希望你得到你。 With reference to this question,我修改了答案,以便它适合你。希望这是您正在寻找的:

import json

data = {
  "library": [
    {
      "_type": "Host",
      "parameters": '{"property1":"value1","property2":"value2"}',
      "superclassOf": [
        {
          "_type": "LinuxHost",
          "superclassOf": [
            {
              "_type": "Ubuntu",
              "superclassOf": [
                {
                  "_type": "Ubuntu1604",
                  "parameters": '{"property1":"value1","property2":"value2"}'
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}


# if you want to modify a specific key's value where you only know the key
def replace(data, key_match, repl):
    if isinstance(data, dict):
        return {k: replace((v if k != key_match else repl), key_match, repl) for k, v in data.items()}
    elif isinstance(data, list):
        return [replace(i, key_match, repl) for i in data]
    elif isinstance(data, str):
        try:
            data = json.loads(data)
            return replace(data, key_match, repl)
        except ValueError:
            return data
    else:
        return data

print(replace(data, "property1", "Modified"))
# {'library': [{'_type': 'Host', 'parameters': {'property1': 'Modified', 'property2': 'value2'}, 'superclassOf': [{'_type': 'LinuxHost', 'superclassOf': [{'_type': 'Ubuntu', 'superclassOf': [{'_type': 'Ubuntu1604', 'parameters': {'property1': 'Modified', 'property2': 'value2'}}]}]}]}]}

编辑

如果你只想转换json。

def convertJSON(data):
    if isinstance(data, dict):
        return {k: convertJSON(v) for k, v in data.items()}
    elif isinstance(data, list):
        return [convertJSON(i) for i in data]
    elif isinstance(data, str):
        try:
            data = json.loads(data)
            return convertJSON(data)
        except ValueError:
            return data
    else:
        return data

print(convertJSON(data))
# {'library': [{'_type': 'Host', 'parameters': {'property1': 'value1', 'property2': 'value2'}, 'superclassOf': [{'_type': 'LinuxHost', 'superclassOf': [{'_type': 'Ubuntu', 'superclassOf': [{'_type': 'Ubuntu1604', 'parameters': {'property1': 'value1', 'property2': 'value2'}}]}]}]}]}

【讨论】:

  • 嗨,我不想替换键的值。我只想在有一个字符串提醒 json 结构的地方使用 json.loads
  • 那么只需要修改replace方法即可。我在答案中添加了修改方法
猜你喜欢
  • 1970-01-01
  • 2020-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-18
相关资源
最近更新 更多