2016-10-03 3 views
0

Ich lese JSON in mein Skript und erstelle eine Liste mit Wörterbüchern.Seltsames Verhalten beim Anhängen eines Wörterbuchs zur Liste

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

Mein Code:

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) 

Das Problem ist, dass die Werte in userinfo_list so schnell überschrieben werden wie meine JSON hat zwei Unterschlüssel (table*).

Dies ist die Ausgabe erhalte ich, was keinen Sinn macht:

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

Daten nicht überschreiben. Versuchen Sie immer, neue Listen, neue dicts, alles neue zu erstellen - wenn der RAM-Speicher es Ihnen erlaubt - und Sie werden es in 99% der Fälle erlauben. –

Antwort

2

Du jede Iteration die gleichen einzelnen Wörterbuch neu anhängt:

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 

Anfügen tut nicht Erstellen Sie eine Kopie, sodass Sie mehrere Verweise auf dasselbe Wörterbuch erhalten und nur die letzte Änderung angezeigt wird. Sie machen den gleichen Fehler mit dem userinfo Wörterbuch.

Erstellen Sie ein neues Wörterbuch in die Schleife:

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) 

Sie können nur die Schlüssel-Wert-Paare direkt angeben, wenn das Wörterbuch zu erstellen:

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

und dies kann mit einem vereinfacht werden list comprehension zu:

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

Beachten Sie, dass Sie dict.keys() nicht aufrufen müssen, um ein Wörterbuch zu durchlaufen. Sie können direkt über das Wörterbuch mit den exakt gleichen Ergebnissen loopen. Sie wollen wahrscheinlich eine Schleife über .items() statt und vermeiden den Schlüssel jedes Mal den Wert zu sehen ist, und .values() verwenden, wenn Sie tatsächlich den Schlüssel nicht brauchen überhaupt:

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) 

Die Erstellung von Wörterbüchern pro Tisch pro Firma kann auch durch eine Liste Verständnis ersetzt werden, aber an diesem Punkt wird es wahrscheinlich für zukünftige Leser leichter zu verstehen, verschachtelte for Schleifen zu bleiben.

Die oben jetzt produziert:

[{'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'}]}] 

aus Ihren Beispieldaten (und meine eigenen Definition von generate_password()).

+0

Das funktioniert einwandfrei, aber ich konnte Ihren Code nicht an meinen aktualisierten JSON anpassen. Bitte sehen Sie meinen ursprünglichen Post für aktualisierten JSON. – rhillhouse

+0

@ou_snaaksie: das wäre normalerweise eine neue Frage. Sie müssen die Schlüssel jedes 'db' Wörterbuchs hier filtern:' für Tabellenname, Tabelle in db.items(): ',' ​​wenn nicht Tabellenname.startswith ('Tabelle'): fortfahren '(anstelle des aktuellen 'für Tabelle in db.values ​​(): 'loop) würde jeden Schlüssel überspringen, der nicht mit' 'table'' beginnt, wie '' lang''. –

Verwandte Themen