def flatten_dict(data, parent_name="", sep=".", key_converter=None, skip_key_check=None):

    """
    Flattens a dictionary to a single layer with child keys separated by `sep` charactor

    Example:
    input:
        parent_name = "root"
        data = {
            "parent_obj": {
                "child_obj": {
                    "grand_child_obj": "my value"
                }
            },
            "foo": "bar"
        }
    output:
        {
            "root.parent_obj.child_obj.grand_child_obj": "my value",
            "root.foo": "bar"
        }

    """
    if not skip_key_check:
        skip_key_check = lambda *_: False

    flattened = {}

    for key, val in data.items():
        child_name = key if not parent_name else f"{parent_name}{sep}{key}"
        if isinstance(val, dict) and not skip_key_check(child_name):
            flattened.update(
                flatten_dict(
                    val, parent_name=child_name, sep=sep, key_converter=key_converter, skip_key_check=skip_key_check
                )
            )
        else:
            if key_converter:
                child_name = key_converter(child_name)
            flattened[child_name] = val

    return flattened