def serialize(self, request, contents, serializer = None, lazy = True):
    """
    Serializes the provided contents (wither map or list) using the
    infra-structure (serializer) that is currently defined for the
    request.

    An optional serializer attribute may be used to "force" the serializer
    that is going to be used in the contents serialization. This value
    may be either the concrete serializer instance or a string representing
    the type of serializer to be used (runtime resolution).

    The definition of the serializer is not part of the method and
    such behavior should be defined by the upper layers.

    The resulting data from the serialization is set as the contents
    for the current request and the proper mime type defined.

    :type request: Request
    :param request: The request object that is going to be used
    as reference for the retrieval of the serializer object and for
    the setting of the serialization result contents.
    :type contents: List/Dictionary
    :param contents: The contents that are going to be serialized using
    the context defined in the request.
    :type serializer: Object
    :param serializer: The serializer (protocol) compliant object that
    is going to be used for the "forced" serialization process.
    :type lazy: bool
    :param lazy: If a lazy based serialization process should be used
    in case there's such support from the serializer.
    :rtype: String/Generator
    :return: The final serialized value that may be used for reference,
    please note that this value should not be set again in the request
    as that may create some unnecessary performance issues.
    """

    # in case the provided serializer value is string based it must
    # be "resolved" using the default string based plugin resolution
    # as the serializer value must always be object compliant
    if type(serializer) == str: serializer = getattr(self.plugin, serializer + "_plugin")

    # verifies if the serializer attribute is defined in the provided
    # request if that's the case and there's no provided serializer
    # such value is going to be used as the serializer for the contents
    is_defined = hasattr(request, "serializer")
    if is_defined: serializer = serializer or request.serializer
    if not serializer: return

    # retrieves the output (character) encoding value from the request
    # so that it may be used for the lazy version of the dumps operation
    # for the generation of the data, as required by specification
    encoding = request.get_encoding()

    # verifies if lazy dumping support exists for the current serializer
    # and if that's the case and lazy serialization is requested the lazy
    # mode is enabled so that a generator based strategy is used
    has_lazy = hasattr(serializer, "dumps_lazy")
    lazy = lazy and has_lazy

    # runs the serialization process on the contents (dumps call) and
    # then retrieves the mime type for together with the data string
    # value set the contents in the current request
    if lazy: data = self.dumps_lazy(serializer, contents, encoding = encoding)
    else: data = serializer.dumps(contents)
    mime_type = serializer.get_mime_type()
    self.set_contents(request, data, content_type = mime_type)

    # returns the final serialized data to the caller method so that it
    # may be inspected and analyzed to check for any issue, it may also
    # be re-used for a different context that the request one
    return data