【问题标题】:How to walk through nested JSON object and update values in python?如何遍历嵌套的 JSON 对象并在 python 中更新值?
【发布时间】:2021-04-07 14:15:45
【问题描述】:

我有一个 JSON 对象,我想遍历并检查/更新所有字符串叶节点。我不知道 JSON 的深度(它是嵌套用户界面的表示),所以我想递归地遍历 JSON 对象。

下面的代码演示了我想要尝试和做的事情,我已经尝试了一些不同的尝试 (https://nvie.com/posts/modifying-deeply-nested-structures/),但我似乎无法做到正确。我要么得到一个“迭代期间字典改变大小”,要么得到一个“键必须是 str、int、float、bool 或 None,而不是元组”错误。

import json

# function for iterating through every JSON item
def walk(obj, parent_first=True):

    # Top down?
    if parent_first:
        yield (), obj

    # For nested objects, the key is the path component.
    if isinstance(obj, dict):
        children = obj.items()

    # For nested lists, the position is the path component.
    elif isinstance(obj, (list, tuple)):
        children = enumerate(obj)

    # Scalar values have no children.
    else:
        children = []

    # Recurse into children
    for key, value in children:
        for child_path, child in walk(value, parent_first):
            yield (key,) + child_path, child

    # Bottom up?
    if not parent_first:
        yield (), obj

def Test():
  
  response = """
  {
      "Name":"Mixed Listbox",
      "Type":"ListBox",
      "Visible?":true,
      "Enabled State":"Enabled",
      "Value":0,
      "All Items":[
        "Non-Unicode",
        "FFFE55006E00690063006F0064006500"
      ]
  }
  """
  
  response = json.loads(response)

  # iterate through each item in the JSON object and update the string items
  for path, value in walk(response):
    # if the JSON item is a string
    if isinstance(value,str):
      # update the string value
      response[path] = 'string: ' + value
Traceback (most recent call last):   File "<string>", line 56, in <module> File "<string>", line 50, in Test   File "<string>", line 23, in walk RuntimeError: dictionary changed size during iteration

预期输出

  response = """
  {
      "Name":"string: Mixed Listbox",
      "Type":"string: ListBox",
      "Visible?":true,
      "Enabled State":"string: Enabled",
      "Value":0,
      "All Items":[
        "string: Non-Unicode",
        "string: FFFE55006E00690063006F0064006500"
      ]
  }
  """

【问题讨论】:

  • 你能显示你的错误的完整堆栈跟踪吗?
  • 是的 - 我现在已将其添加到帖子中。
  • 你发布的方式我看不到错误在哪一行
  • 我将代码分离出来并通过在线 python 解释器运行它,以便它尽可能简单/直接的示例。 onlinegdb.com/Bk4x8rjrO
  • 在迭代字典时不能向字典添加键。

标签: python json recursion


【解决方案1】:

这是我实现的最终解决方案,它没有使用通用的“walk”函数,但它确实通过 JSON 对象递归并更新任何字符串项。我缺少的一点是返回并更新对象,而不是尝试返回路径然后更新它。

  # converts unicode hex strings into strings for known types in the return data
  def handleUnicode(self,response):
     
    def decode_dict(obj):
    
      # if dict, children are items
      if isinstance(obj,dict):
        children = obj.items()
    
      # if list/tuple, enumerate items    
      elif isinstance(obj,(list,tuple)):
        children = enumerate(obj)
    
      # scalar values have no children  
      else:
        children = []
        # if the obj is a string, decode it
        if isinstance(obj,str):
            obj = self.decodeBomHexString(obj)
      
      # iterate through the children (recursively)    
      for key,value in children:
        obj[key] = decode_dict(value)
      
      return obj    
      
    response = decode_dict(response)
    
    return response

【讨论】:

    猜你喜欢
    • 2019-04-24
    • 2016-04-21
    • 2018-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多