def flatten(dictionary, children=None): if children is None: children = [] new_dict = {} for name, value in dictionary.items(): if isinstance(value, dict): if len(value) != 0: children.append(name) new_dict.update(flatten(value, children)) children.pop() elif len(children) == 0: new_dict[name] = "" else: new_dict["/".join(children) + "/" + name] = "" elif len(children) == 0: new_dict[name] = value else: new_dict["/".join(children) + "/" + name] = value return new_dict if __name__ == '__main__': test_input = {"key": {"deeper": {"more": {"enough": "value"}}}} print(' Input: {}'.format(test_input)) print('Output: {}'.format(flatten(test_input))) # These "asserts" using only for self-checking and not necessary for auto-testing assert flatten({"key": "value"}) == {"key": "value"}, "Simple" assert flatten( {"key": {"deeper": {"more": {"enough": "value"}}}} ) == {"key/deeper/more/enough": "value"}, "Nested" assert flatten({"empty": {}}) == {"empty": ""}, "Empty value" assert flatten({"name": { "first": "One", "last": "Drone"}, "job": "scout", "recent": {}, "additional": { "place": { "zone": "1", "cell": "2"}}} ) == {"name/first": "One", "name/last": "Drone", "job": "scout", "recent": "", "additional/place/zone": "1", "additional/place/cell": "2"} var = {"job/1": "scout", "recent/places/earth/NY": "2017", "job/3": "writer", "job/2": "worker", "job/5": "learner", "job/4": "reader", "recent/places/earth/NP": "", "recent/places/earth/Louvre": "2015", "recent/times/XX/1964": "Yes", "recent/times/XXI/2064": "Nope", "name/first": "Second", "name/last": "Drone", "name/nick": ""} assert flatten({"name": {"first": "Second", "last": "Drone", "nick": {}}, "job": {"1": "scout", "2": "worker", "3": "writer", "4": "reader", "5": "learner"}, "recent": {"places": {"earth": {"Louvre": "2015", "NY": "2017", "NP": ""}}, "times": {"XX": {"1964": "Yes"}, "XXI": {"2064": "Nope"}}}}) == var print('You all set. Click "Check" now!')