def METHOD_NAME(cls, d, reading=False):
    """
    Updates invalid attributes of a dict by encoding disallowed characters
    and, when `reading=False`, expanding dotted keys into nested dicts for
    `NESTED_RESERVED_ATTRIBUTES`
    :param d: dict
    :param reading: boolean.
    :return: dict
    Example:
        >>> d = {
                '_validation_status.other.nested': 'lorem',
                '_validation_status.uid': 'approved',
                'my.string.with.dots': 'yes'
            }
        >>> MongoHelper.to_safe_dict(d)
            {
                'myLg==stringLg==withLg==dots': 'yes',
                '_validation_status': {
                    'other': {
                        'nested': 'lorem'
                    },
                    'uid': 'approved'
                }
            }
        >>> MongoHelper.to_safe_dict(d, reading=True)
            {
                'myLg==stringLg==withLg==dots': 'yes',
                '_validation_status.other.nested': 'lorem',
                '_validation_status.uid': 'approved'
            }
    """
    for key, value in list(d.items()):
        if type(value) == list:
            value = [cls.METHOD_NAME(e, reading=reading)
                     if type(e) == dict else e for e in value]
        elif type(value) == dict:
            value = cls.METHOD_NAME(value, reading=reading)
        elif key == '_id':
            try:
                d[key] = int(value)
            except ValueError:
                # if it is not an int don't convert it
                pass
        if cls._is_nested_reserved_attribute(key):
            # If we want to write into Mongo, we need to transform the dot delimited string into a dict
            # Otherwise, for reading, Mongo query engine reads dot delimited string as a nested object.
            # Drawback, if a user uses a reserved property with dots, it will be converted as well.
            if not reading and key.count(".") > 0:
                tree = {}
                t = tree
                parts = key.split(".")
                last_index = len(parts) - 1
                for index, part in enumerate(parts):
                    v = value if index == last_index else {}
                    t = t.setdefault(part, v)
                del d[key]
                first_part = parts[0]
                if first_part not in d:
                    d[first_part] = {}
                # We update the main dict with new dict.
                # We use dict_for_mongo again on the dict to ensure, no invalid characters are children
                # elements
                d[first_part].update(cls.METHOD_NAME(tree[first_part]))
        elif cls.is_attribute_invalid(key):
            del d[key]
            d[cls.encode(key)] = value
    return d