I am trying to parse json with deep nesting, up to 10 elements, how to handle an exception when there is no key in the dictionary?

d = json.loads(file) print( d['date'], d['тип'], d['инн'], d['кпп'], d['огрн'], d['имяПолное'], d['имяКраткое'], d['оснВидДеятельности']['код'], d['оснВидДеятельности']['наим'], d['свАдрес']['адресРФ']['кодАдрКладр'] 

) For example, there is no last element (maybe in another file), I get an error:

 d['свАдрес']['адресРФ']['кодАдрКлад'] KeyError: 'кодАдрКлад' 

I wanted to write a handler, but it didn’t work out that much, the error is the same

 def get_err(s): try: return s except: return '' 

In print, I show everything for debugging, ideally you need to collect the key values ​​into a string with a separator; for subsequent import to the database

    5 answers 5

    s = d['тип'] + ';' + d['свАдрес']['адресРФ']['кодАдрКладр'] s = d['тип'] + ';' + d['свАдрес']['адресРФ']['кодАдрКладр'] . If d['свАдрес']['адресРФ']['кодАдрКладр'] not in the dictionary then None or space

    To return a value by key or None , you can use d.get('тип') .

    To return a value to the specified path specified by the list of nested keys :

     from functools import reduce def get_by_path(d, *path, default=None): try: return reduce(dict.__getitem__, path, d) except KeyError: return default 

    Example: get_by_path(d, 'оснВидДеятельности', 'код') or:

     s = ';'.join([get_by_path(d, *path, default=' ') for path in [['тип'], ['свАдрес', 'адресРФ', 'кодАдрКладр']]]) 
    • Thank you, simple solution) - ss_beer

    You need to catch the exception when you access the key, i.e.:

     try d['some_key'] except KeyError: return '' 
    • And how, for example, to pass a key chain to a function? I do not know which key may not be. Or every access to the key in a try..except wrap? - ss_beer
    • one
      You can use @ss_beer in try to either wrap an entire piece of code at once, or simply call the function in which you expect an exception. But you need to understand that in this case the whole part of the wrapped code that comes after the problematic line will not be executed. - Xander
    • A little bit wrong, look, I want to get a csv line at the output. do so s = d ['type'] + ';' + d ['svaddress'] ['address RF'] ['code AdrKladr']. If d ['svadress'] ['address RF'] ['code AdrKladr'] is not in the dictionary then None or space. And so handle each key, for example, the type may also not be - ss_beer

    You can do something like this:

     d = json.loads(file) class JsonNode(dict): def __getitem__(self, key): if key in self: item = super().__getitem__(key) if isinstance(item, dict): return JsonNode(item) else: return item else: return JsonNode() def __repr__(self): return str(dict(self)) if self else str(None) d = JsonNode(d) 

    When accessing by a non-existing key, returns an empty object. It supports arbitrary nesting, even if after a non-existent key there are several more plug-ins.

    When outputting via print or converting to a string, an empty object is displayed as None.

    I wrote on my hand, so maybe something needs to be done and debugged, but in general the principle is this.

    • Thanks, cool solution :) - ss_beer

    I finally decided so, can someone come in handy:

     def check_sl(d, k): if k[0] in d.keys(): try: if d[k[0]] is None: # print('1') return ' ' else: if len(k) > 1: # print('2') return check_sl(d[k[0]],k[1:]) else: # print('3', str(d[k[0]])) return str(d[k[0]]) except: return ' ' else: return ' ' check_sl(d,['оснВидДеятельности','код']) 

    Transfer keys list.

      You can not handle the exception, and set the default value for a nonexistent key:

       from collections import defaultdict d = json.loads(file) new_json = defaultdict( lambda x=None: 'Ключ не найден', d )