import six


def convert_recursive_helper(converter, data):
  """
  Given JSON-like data (a nested collection of lists or arrays), which may include Action tuples,
  replaces all primitive values with converter(value). It should be used as follows:

      def my_convert(data):
        if data needs conversion:
          return converted_value
        return convert_recursive_helper(my_convert, data)
  """
  if isinstance(data, dict):
    return {converter(k): converter(v) for k, v in six.iteritems(data)}
  elif isinstance(data, list):
    return [converter(el) for el in data]
  elif isinstance(data, tuple):
    return type(data)(*[converter(el) for el in data])
  else:
    return data