2016-10-03 87 views
0

我正在将JSON读入我的脚本并构建一个由字典组成的列表。将字典附加到列表中时出现奇怪行为

我的JSON:

{ 
    "JMF": { 
     "table1": { 
      "email": "[email protected]", 
      "guests": [ 
      "test1", 
      "test2" 
      ] 
     }, 
     "table2": { 
      "email": "[email protected]", 
      "guests": [ 
      "test3" 
      ] 
     } 
    }, 
    "JMC": { 
     "table3": { 
     "email": "[email protected]", 
     "guests": [ 
      "test11" 
     ] 
     } 
    }, 
    "JMD": { 
     "table4": { 
     "email": "[email protected]", 
     "guests": [ 
      "test12" 
     ] 
     }, 
     "table5": { 
     "email": "[email protected]", 
     "guests": [ 
      "test17" 
     ] 
     } 
    } 
} 

我的代码:

def get_json(): 
    userinfo_list = [] 
    with open('guest_users.json') as json_file: 
     json_file = json.load(json_file) 
     keys = json_file.keys() 
     for key in keys: 
      userinfo = {} 
      for table_key in json_file[key].keys(): 
       email = json_file[key][table_key]['email'] 
       users_dict = {} 
       users_list = [] 
       for user in json_file[key][table_key]['guests']: 
        users_dict['username'] = user 
        users_dict['password'] = generate_password() 
        users_list.append(users_dict) 
       userinfo['company'] = key 
       userinfo['email'] = email 
       userinfo['userinfo'] = users_list 
       userinfo_list.append(userinfo) 
       print(userinfo) 
       print(userinfo_list) 

的问题是,我的JSON有两个子键(table*)在userinfo_list价值得到尽快覆盖。

这是输出我得到的,这没有任何意义:

{'userinfo': [{'username': 'test11', 'password': '1fEAg0'}], 'email': '[email protected]', 'company': 'JMC'} 
[{'userinfo': [{'username': 'test11', 'password': '1fEAg0'}], 'email': '[email protected]', 'company': 'JMC'}] 
{'userinfo': [{'username': 'test17', 'password': 'A8Jue5'}], 'email': '[email protected]', 'company': 'JMD'} 
[{'userinfo': [{'username': 'test11', 'password': '1fEAg0'}], 'email': '[email protected]', 'company': 'JMC'}, {'userinfo': [{'username': 'test17', 'password': 'A8Jue5'}], 'email': '[email protected]', 'company': 'JMD'}] 
{'userinfo': [{'username': 'test12', 'password': '0JSpc0'}], 'email': '[email protected]', 'company': 'JMD'} 
[{'userinfo': [{'username': 'test11', 'password': '1fEAg0'}], 'email': '[email protected]', 'company': 'JMC'}, {'userinfo': [{'username': 'test12', 'password': '0JSpc0'}], 'email': '[email protected]', 'company': 'JMD'}, {'userinfo': [{'username': 'test12', 'password': '0JSpc0'}], 'email': '[email protected]', 'company': 'JMD'}] 
{'userinfo': [{'username': 'test2', 'password': 'GagQ59'}, {'username': 'test2', 'password': 'GagQ59'}], 'email': '[email protected]', 'company': 'JMF'} 
[{'userinfo': [{'username': 'test11', 'password': '1fEAg0'}], 'email': '[email protected]', 'company': 'JMC'}, {'userinfo': [{'username': 'test12', 'password': '0JSpc0'}], 'email': '[email protected]', 'company': 'JMD'}, {'userinfo': [{'username': 'test12', 'password': '0JSpc0'}], 'email': '[email protected]', 'company': 'JMD'}, {'userinfo': [{'username': 'test2', 'password': 'GagQ59'}, {'username': 'test2', 'password': 'GagQ59'}], 'email': '[email protected]', 'company': 'JMF'}] 
{'userinfo': [{'username': 'test3', 'password': 'U9gP0j'}], 'email': '[email protected]', 'company': 'JMF'} 
[{'userinfo': [{'username': 'test11', 'password': '1fEAg0'}], 'email': '[email protected]', 'company': 'JMC'}, {'userinfo': [{'username': 'test12', 'password': '0JSpc0'}], 'email': '[email protected]', 'company': 'JMD'}, {'userinfo': [{'username': 'test12', 'password': '0JSpc0'}], 'email': '[email protected]', 'company': 'JMD'}, {'userinfo': [{'username': 'test3', 'password': 'U9gP0j'}], 'email': '[email protected]', 'company': 'JMF'}, {'userinfo': [{'username': 'test3', 'password': 'U9gP0j'}], 'email': '[email protected]', 'company': 'JMF'}] 
+0

不要覆盖数据。总是尝试创建新的列表,新的字典,新的一切 - 如果RAM内存允许你 - 并且它可以让你在99%的情况下。 –

回答

2

您重新追加同一个字典每次迭代:

users_dict = {} # only one copy of this dictionary is ever created 
users_list = [] 
for user in json_file[key][table_key]['guests']: 
    users_dict['username'] = user 
    users_dict['password'] = generate_password() 
    users_list.append(users_dict) # appending a reference to users_dict 

追加不创建副本,因此您可以获得对同一字典的多个引用,并且只会看到反映的最后更改。您在userinfo字典中犯了同样的错误。

创建一个新的字典循环:

users_list = [] 
for user in json_file[key][table_key]['guests']: 
    users_dict = {} 
    users_dict['username'] = user 
    users_dict['password'] = generate_password() 
    users_list.append(users_dict) 

创建字典时,你可以直接指定键值对:

users_list = [] 
for user in json_file[key][table_key]['guests']: 
    users_dict = { 
     'username': user, 
     'password': generate_password() 
    } 
    users_list.append(users_dict) 

,这可以用一个简化list comprehension至:

users_list = [{'username': user, 'password': generate_password()} 
       for user in json_file[key][table_key]['guests']] 

请注意,您无需拨打dict.keys()即可循环查看字典。您可以直接循环通过字典具有完全相同的结果。你可能要循环.items()代替,并避免查找关键每次的价值,并使用.values()当你实际上并不需要的关键都:

userinfo_list = [] 
for company, db in json_file.items(): 
    for table in db.values(): 
     userinfo = { 
      'company': company, 
      'email': table['email'], 
      'userinfo': [ 
       {'username': user, 'password': generate_password()} 
       for user in table['guests']] 
     } 
     userinfo_list.append(userinfo) 

每桌字典的创建每个公司也可以用列表理解取代,但是在这一点上坚持嵌套for循环可能会更容易理解未来的读者。

上面现在生产:

[{'company': 'JMF', 
    'email': '[email protected]', 
    'userinfo': [{'password': 'random_password_really', 'username': 'test1'}, 
       {'password': 'random_password_really', 'username': 'test2'}]}, 
{'company': 'JMF', 
    'email': '[email protected]', 
    'userinfo': [{'password': 'random_password_really', 'username': 'test3'}]}, 
{'company': 'JMC', 
    'email': '[email protected]', 
    'userinfo': [{'password': 'random_password_really', 'username': 'test11'}]}, 
{'company': 'JMD', 
    'email': '[email protected]', 
    'userinfo': [{'password': 'random_password_really', 'username': 'test12'}]}, 
{'company': 'JMD', 
    'email': '[email protected]', 
    'userinfo': [{'password': 'random_password_really', 'username': 'test17'}]}] 

从样本数据(和我自己的generate_password()定义)。

+0

这个工作完美,但我无法适应你的代码到我更新的JSON。请参阅我的原始帖子以获取更新的JSON。 – rhillhouse

+0

@ou_snaaksie:那通常是一个新问题。你需要在这里过滤每个'db'字典的键:'对于tablename,db.items()中的表:'',如果不是tablename.startswith('table'):continue'(而不是当前的'for table在分贝。values():'loop)会跳过任何不以''table'开头的键,比如''lang''。 –