def build_param_structure(params, target, value, index=None):
    """
    This method provides a basic reverse JMESPath implementation that
    lets you go from a JMESPath-like string to a possibly deeply nested
    object. The ``params`` are mutated in-place, so subsequent calls
    can modify the same element by its index.

        >>> build_param_structure(params, 'test[0]', 1)
        >>> print(params)
        {'test': [1]}

        >>> build_param_structure(params, 'foo.bar[0].baz', 'hello world')
        >>> print(params)
        {'test': [1], 'foo': {'bar': [{'baz': 'hello, world'}]}}

    """
    pos = params
    parts = target.split('.')

    # First, split into parts like 'foo', 'bar[0]', 'baz' and process
    # each piece. It can either be a list or a dict, depending on if
    # an index like `[0]` is present. We detect this via a regular
    # expression, and keep track of where we are in params via the
    # pos variable, walking down to the last item. Once there, we
    # set the value.
    for i, part in enumerate(parts):
        # Is it indexing an array?
        result = INDEX_RE.search(part)
        if result:
            if result.group(1):
                if result.group(1) == '*':
                    part = part[:-3]
                else:
                    # We have an explicit index
                    index = int(result.group(1))
                    part = part[: -len(str(index) + '[]')]
            else:
                # Index will be set after we know the proper part
                # name and that it's a list instance.
                index = None
                part = part[:-2]

            if part not in pos or not isinstance(pos[part], list):
                pos[part] = []

            # This means we should append, e.g. 'foo[]'
            if index is None:
                index = len(pos[part])

            while len(pos[part]) <= index:
                # Assume it's a dict until we set the final value below
                pos[part].append({})

            # Last item? Set the value, otherwise set the new position
            if i == len(parts) - 1:
                pos[part][index] = value
            else:
                # The new pos is the *item* in the array, not the array!
                pos = pos[part][index]
        else:
            if part not in pos:
                pos[part] = {}

            # Last item? Set the value, otherwise set the new position
            if i == len(parts) - 1:
                pos[part] = value
            else:
                pos = pos[part]

    This method provides a basic reverse JMESPath implementation that
    lets you go from a JMESPath-like string to a possibly deeply nested
    object. The ``params`` are mutated in-place, so subsequent calls
    can modify the same element by its index.

        >>> build_param_structure(params, 'test[0]', 1)
        >>> print(params)
        {'test': [1]}

        >>> build_param_structure(params, 'foo.bar[0].baz', 'hello world')
        >>> print(params)
        {'test': [1], 'foo': {'bar': [{'baz': 'hello, world'}]}}

    
boto3/resources/params.py