def set_metadata(self, obj, metadata, clear=False, prefix=None):
        """
        Accepts a dictionary of metadata key/value pairs and updates the
        specified object metadata with them.

        If 'clear' is True, any existing metadata is deleted and only the
        passed metadata is retained. Otherwise, the values passed here update
        the object's metadata.

        By default, the standard object metadata prefix ('X-Object-Meta-') is
        prepended to the header name if it isn't present. For non-standard
        headers, you must include a non-None prefix, such as an empty string.
        """
        # Add the metadata prefix, if needed.
        if prefix is None:
            prefix = OBJECT_META_PREFIX
        massaged = _massage_metakeys(metadata, prefix)
        cname = utils.get_name(self.container)
        oname = utils.get_name(obj)
        new_meta = {}
        # Note that the API for object POST is the opposite of that for
        # container POST: for objects, all current metadata is deleted,
        # whereas for containers you need to set the values to an empty
        # string to delete them.
        if not clear:
            obj_meta = self.get_metadata(obj, prefix=prefix)
            new_meta = _massage_metakeys(obj_meta, prefix)
        utils.case_insensitive_update(new_meta, massaged)
        # Remove any empty values, since the object metadata API will
        # store them.
        to_pop = []
        for key, val in six.iteritems(new_meta):
            if not val:
                to_pop.append(key)
        for key in to_pop:
            new_meta.pop(key)
        uri = "/%s/%s" % (cname, oname)
        resp, resp_body = self.api.method_post(uri, headers=new_meta)