2
votes

Impossible de renvoyer le champ "valide" à partir du dictionnaire analysé

J'ai le json dans le format suivant:

# Called by
get_system_state(myDict, 1)

Je stocke ceci dans un dictionnaire et je dois effectuer un traitement à ce sujet.

Pour un "Tid ", Je veux pouvoir renvoyer la valeur" @default "dans la partie" status ". Par exemple, si je demande "Tid" = 1, je devrais obtenir la sortie suivante.

SORTIE ATTENDUE:

def get_system_state(myDict, id):
    for i in  ["id", "@default"]:
        print (myDict.get(i))
    if any(c == id_type for c in myDict.values()):
        yield {i: myDict.get(i) for i in ["id", "@default"]}
    else:
        for i in myDict.values():
            if isinstance(i, dict):
                yield from get_system_state(i, id_type)

J'ai la méthode suivante pour le moment, mais cela me renvoie ceci et je ne comprends pas pourquoi.

{ "Tid": null,
  "status": null
} 

Ma méthode:

{ "Tid": "1",
  "status": "0"  -->this is the value from the @default attribute
} 
# note that the "status" value is the attribute @default.
myDict =
{
  "Garden": {
    "GroundFloor": {
      "@loc": "porch",
      "@myID": "35C",
      "Tid": "1",
      "InfoList": {
        "status": {
          "@default": "0",
          "@myID": "20C"
        },
        "count": {
          "@default": "0",
          "@myID": "1"
        }
      }
    },
      "TopFloor": {
      "@loc": "backyard",
      "@myID": "35C",
      "Tid": "2",
      "InfoList": {
        "status": {
          "@default": "0",
          "@myID": "20D"
        },
        "count": {
          "@default": "0",
          "@myID": "2"
        }
      }
    }
  },
"BackYard": {
    "GroundFloor": {
      "@loc": "porch",
      "@myID": "35C",
      "Tid": "3",
      "InfoList": {
        "status": {
          "@default": "0",
          "@myID": "20C"
        },
        "count": {
          "@default": "0",
          "@myID": "1"
        }
      }
    },
      "TopFloor": {
      "@loc": "backyard",
      "@myID": "35C",
      "Tid": "4",
      "InfoList": {
        "status": {
          "@default": "0",
          "@myID": "20D"
        },
        "count": {
          "@default": "0",
          "@myID": "2"
        }
      }
    }
  },
... many more nested layers...
}


8 commentaires

TopFloor " vous manquez le devis


Accédez à ce site Web et validez le json - https://jsonlint.com/


@Nitin l'a validé et mis à jour.


@LauraSmith Permettez-moi de vérifier pourquoi cela se produit. Je reviendrai vers toi


@LauraSmith Quel est votre résultat attendu?


@bharatk Je l'ai mis à jour dans le code. Il est étiqueté SORTIE ATTENDUE.


@LauraSmith qu'en est-il du reste d'une partie du dictionnaire si une condition est une correspondance, ou si vous voulez simplement ajouter status comme clé et @default est une valeur en dehors du dictionnaire imbriqué si la condition correspond


Je veux pouvoir renvoyer le résultat avec le "Tid" et sa valeur et le "status" et sa valeur qui est le @default lorsque j'interroge pour un "Tid" spécifique dans la méthode get_system_state. À cette méthode, je passe le myDict et l'id.


3 Réponses :


1
votes

Je viens de changer votre dictionnaire "Tid": "2", "InfoList": {"status": {"@default": "1", "@ myID": "20D"}, code> @ valeur par défaut à des fins de test.

  • isdigit () méthodes renvoie "True" si tous les caractères de la chaîne sont des chiffres, sinon, il renvoie "False".

def get_system_state(myDict, id):
    for k1,v1 in myDict.items():
        for k,v in v1.items():
            for x in v:
                if 'Tid' in v and v['Tid'] is not None and v['Tid'].isdigit() and int(v['Tid']) == id:
                    return [{'Tid':id,'status':v['InfoList']['status']['@default']}]

O/P:

[{'Tid': 2, 'status': '1'}]

si vous passez id=2

new_dict = get_system_state(myDict, 2)

O/P:

[{'Tid': 1, 'status': '0'}]

Update:

si un dictionnaire n'a pas le "Jardin" comme dictionnaire de premier niveau

myDict ={
  "Garden": {
    "GroundFloor": {
      "@loc": "porch",
      "@myID": "35C",
      "Tid": "1",
      "InfoList": {"status": { "@default": "0","@myID": "20C"},
      "count": {"@default": "0","@myID": "1"}
      }
    },
      "TopFloor": {
      "@loc": "backyard",
      "@myID": "35C",
      "Tid": "2",
      "InfoList": { "status": { "@default": "1","@myID": "20D"},
      "count": {"@default": "0","@myID": "2" }
      }
    }
  }
}


def get_system_state(myDict, id):
    for k,v in myDict['Garden'].items():
        for x in v:
            if 'Tid' in v and v['Tid'] is not None and v['Tid'].isdigit() and int(v['Tid']) == id:
                return [{'Tid':id,'status':v['InfoList']['status']['@default']}]

new_dict = get_system_state(myDict, 1)
print(new_dict)


8 commentaires

Par exemple, si le dictionnaire n'a pas la chaîne "Garden" comme nœud de niveau supérieur, comment puis-je le rendre générique dans tous les cas?


J'ai mis à jour myDict dans la question pour refléter ce que je veux dire.


@LauraSmith Essayez maintenant.


Une dernière question, est-il possible que le return {'Tid': id, 'status': v ['InfoList'] ['status'] ['@ default']} renvoie une liste au lieu?


J'ai essayé cette liste de retour ({'Tid': id, 'status': v ['InfoList'] ['status'] ['@ default']} ‌) . Cela me donne une erreur L'objet 'NoneType' n'est pas itérable .


@Laura Smith signifie comme ceci [{'Tid': 2, 'status': '1'}] ou [2,0]


comme le [{'Tid': 2, 'status': '1'}] car je veux l'envoyer à la méthode jsonify . C'est pourquoi je veux retourner une liste et faire quelque chose comme ça si possible, jsonify (key_list sinon key_list sinon key_list [0]) .


@LauraSmith signifie que je n'obtiens aucune erreur. Réponse mise à jour



0
votes

Essayez d'utiliser ceci:

def get_system_state(myDict, id):
    garden_details = myDict.get("Garden", None)
    if garden_details:
        for floor in garden_details:
            Tid = garden_details[floor].get(str("Tid"), None)
            if Tid == str(id):
                return {'Tid': Tid, 'status': garden_details[floor]['InfoList']['status']['@default']}

Vérifiez si cela fonctionne pour vous.


2 commentaires

Je veux le rendre plus générique plutôt que d'utiliser la chaîne "Garden". Je mets à jour myDict pour le montrer.


garden_details = list (myDict.values ​​()) [0] utilisez ceci au lieu de garden_details = myDict.get ("Garden", None) si la position est fixe.



1
votes

Vous pouvez utiliser une récursion simple:

[{'Tid': '1', 'status': '0'}]

Sortie:

data = {'Garden': {'GroundFloor': {'@loc': 'porch', '@myID': '35C', 'Tid': '1', 'InfoList': {'status': {'@default': '0', '@myID': '20C'}, 'count': {'@default': '0', '@myID': '1'}}}, 'TopFloor': {'@loc': 'backyard', '@myID': '35C', 'Tid': '2', 'InfoList': {'status': {'@default': '0', '@myID': '20D'}, 'count': {'@default': '0', '@myID': '2'}}}}, 'BackYard': {'GroundFloor': {'@loc': 'porch', '@myID': '35C', 'Tid': '3', 'InfoList': {'status': {'@default': '0', '@myID': '20C'}, 'count': {'@default': '0', '@myID': '1'}}}, 'TopFloor': {'@loc': 'backyard', '@myID': '35C', 'Tid': '4', 'InfoList': {'status': {'@default': '0', '@myID': '20D'}, 'count': {'@default': '0', '@myID': '2'}}}}}
def get_id(d, id):
   if isinstance(d, dict) and d.get('Tid') == id:
      yield {'Tid':d['Tid'], 'status':d['InfoList']['status']['@default']}
   for i in getattr(d, 'values', lambda :[])():
      yield from get_id(i, id)

print(list(get_id(data, '1')))


0 commentaires