Skip to content

Instantly share code, notes, and snippets.

@wrouesnel
Last active November 3, 2021 02:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wrouesnel/10db40ac02483af905d91d200961fc0f to your computer and use it in GitHub Desktop.
Save wrouesnel/10db40ac02483af905d91d200961fc0f to your computer and use it in GitHub Desktop.
Simple function for recursively iterating JSON-like data in Python
from collections.abc import Mapping
from typing import Any, Callable, Iterable, MutableMapping, MutableSequence
def recurse_object(o: Any,
k=None,
fn: Callable[[Any,Any,Any],Any]=None,
prefn:Callable[[Any,Any],None]=None,
postfn:Callable[[Any,Any,Any,Any],Any]=None,
mapping_cls=dict,
sequence_cls=list) -> Any:
"""
Recurse through an object and apply a function to every key level.
Only applicable to Mapping/Sequence types.
:param o: (any) object to recurse through
:param k: (any) key path of the value that provided the object just requested
:param fn: fn which manipulates the value
:param prefn: prefn called before recursing
:param postfn: postfn called before returning
:param mapping_cls: class initializer for mapping types
:param sequence_cls: class initializer for sequence types
:return:
"""
if fn is None:
fn = lambda i, k, o: i
if prefn is not None:
i = prefn(o,k)
else:
i = o
r: Any = None
if isinstance(i, Mapping):
r: MutableMapping = mapping_cls()
for k,v in i.items():
r[k] = recurse_object(v, k, fn=fn, prefn=prefn, postfn=postfn)
elif isinstance(i, Iterable) and not isinstance(i, (str,bytes)):
r: MutableSequence = sequence_cls()
for k,v in enumerate(i):
r.append(recurse_object(v, k, fn=fn, prefn=prefn, postfn=postfn))
else:
r = fn(i,k,o)
if postfn is not None:
r = postfn(o,k,i,r)
return r
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment