Extract method for Objects; struct tags: json -> mapstructure
diff --git a/openstack/objectstorage/v1/objects/results.go b/openstack/objectstorage/v1/objects/results.go
index b51b840..b9b4084 100644
--- a/openstack/objectstorage/v1/objects/results.go
+++ b/openstack/objectstorage/v1/objects/results.go
@@ -5,6 +5,7 @@
 	"io"
 	"io/ioutil"
 	"strings"
+	"time"
 
 	"github.com/rackspace/gophercloud"
 	"github.com/rackspace/gophercloud/pagination"
@@ -108,12 +109,59 @@
 	}
 }
 
+// DownloadHeader represents the headers returned in the response from a Download request.
+type DownloadHeader struct {
+	AcceptRanges       string    `mapstructure:"Accept-Ranges"`
+	ContentDisposition string    `mapstructure:"Content-Disposition"`
+	ContentEncoding    string    `mapstructure:"Content-Encoding"`
+	ContentLength      int64     `mapstructure:"Content-Length"`
+	ContentType        string    `mapstructure:"Content-Type"`
+	Date               time.Time `mapstructure:"-"`
+	DeleteAt           int       `mapstructure:"X-Delete-At"`
+	ETag               string    `mapstructure:"Etag"`
+	LastModified       time.Time `mapstructure:"-"`
+	ObjectManifest     string    `mapstructure:"X-Object-Manifest"`
+	StaticLargeObject  bool      `mapstructure:"X-Static-Large-Object"`
+	TransID            string    `mapstructure:"X-Trans-Id"`
+}
+
 // DownloadResult is a *http.Response that is returned from a call to the Download function.
 type DownloadResult struct {
 	gophercloud.HeaderResult
 	Body io.ReadCloser
 }
 
+// Extract will return a struct of headers returned from a call to Download. To obtain
+// a map of headers, call the ExtractHeader method on the DownloadResult.
+func (dr DownloadResult) Extract() (DownloadHeader, error) {
+	var dh DownloadHeader
+	if dr.Err != nil {
+		return dh, dr.Err
+	}
+
+	if err := mapstructure.Decode(dr.Header, &dh); err != nil {
+		return dh, err
+	}
+
+	if date, ok := dr.Header["Date"]; ok && len(date) > 0 {
+		t, err := time.Parse(time.RFC1123, dr.Header["Date"][0])
+		if err != nil {
+			return dh, err
+		}
+		dh.Date = t
+	}
+
+	if date, ok := dr.Header["Last-Modified"]; ok && len(date) > 0 {
+		t, err := time.Parse(time.RFC1123, dr.Header["Last-Modified"][0])
+		if err != nil {
+			return dh, err
+		}
+		dh.LastModified = t
+	}
+
+	return dh, nil
+}
+
 // ExtractContent is a function that takes a DownloadResult's io.Reader body
 // and reads all available data into a slice of bytes. Please be aware that due
 // the nature of io.Reader is forward-only - meaning that it can only be read
@@ -131,11 +179,57 @@
 	return body, nil
 }
 
+// GetHeader represents the headers returned in the response from a Get request.
+type GetHeader struct {
+	ContentDisposition string    `mapstructure:"Content-Disposition"`
+	ContentEncoding    string    `mapstructure:"Content-Encoding"`
+	ContentLength      int64     `mapstructure:"Content-Length"`
+	ContentType        string    `mapstructure:"Content-Type"`
+	Date               time.Time `mapstructure:"-"`
+	DeleteAt           int       `mapstructure:"X-Delete-At"`
+	ETag               string    `mapstructure:"Etag"`
+	LastModified       time.Time `mapstructure:"-"`
+	ObjectManifest     string    `mapstructure:"X-Object-Manifest"`
+	StaticLargeObject  bool      `mapstructure:"X-Static-Large-Object"`
+	TransID            string    `mapstructure:"X-Trans-Id"`
+}
+
 // GetResult is a *http.Response that is returned from a call to the Get function.
 type GetResult struct {
 	gophercloud.HeaderResult
 }
 
+// Extract will return a struct of headers returned from a call to Get. To obtain
+// a map of headers, call the ExtractHeader method on the GetResult.
+func (gr GetResult) Extract() (GetHeader, error) {
+	var gh GetHeader
+	if gr.Err != nil {
+		return gh, gr.Err
+	}
+
+	if err := mapstructure.Decode(gr.Header, &gh); err != nil {
+		return gh, err
+	}
+
+	if date, ok := gr.Header["Date"]; ok && len(date) > 0 {
+		t, err := time.Parse(time.RFC1123, gr.Header["Date"][0])
+		if err != nil {
+			return gh, err
+		}
+		gh.Date = t
+	}
+
+	if date, ok := gr.Header["Last-Modified"]; ok && len(date) > 0 {
+		t, err := time.Parse(time.RFC1123, gr.Header["Last-Modified"][0])
+		if err != nil {
+			return gh, err
+		}
+		gh.LastModified = t
+	}
+
+	return gh, nil
+}
+
 // ExtractMetadata is a function that takes a GetResult (of type *http.Response)
 // and returns the custom metadata associated with the object.
 func (gr GetResult) ExtractMetadata() (map[string]string, error) {
@@ -152,22 +246,176 @@
 	return metadata, nil
 }
 
+// CreateHeader represents the headers returned in the response from a Create request.
+type CreateHeader struct {
+	ContentLength int64     `mapstructure:"Content-Length"`
+	ContentType   string    `mapstructure:"Content-Type"`
+	Date          time.Time `mapstructure:"-"`
+	ETag          string    `mapstructure:"Etag"`
+	LastModified  time.Time `mapstructure:"-"`
+	TransID       string    `mapstructure:"X-Trans-Id"`
+}
+
 // CreateResult represents the result of a create operation.
 type CreateResult struct {
 	gophercloud.HeaderResult
 }
 
+// Extract will return a struct of headers returned from a call to Create. To obtain
+// a map of headers, call the ExtractHeader method on the CreateResult.
+func (cr CreateResult) Extract() (CreateHeader, error) {
+	var ch CreateHeader
+	if cr.Err != nil {
+		return ch, cr.Err
+	}
+
+	if err := mapstructure.Decode(cr.Header, &ch); err != nil {
+		return ch, err
+	}
+
+	if date, ok := cr.Header["Date"]; ok && len(date) > 0 {
+		t, err := time.Parse(time.RFC1123, cr.Header["Date"][0])
+		if err != nil {
+			return ch, err
+		}
+		ch.Date = t
+	}
+
+	if date, ok := cr.Header["Last-Modified"]; ok && len(date) > 0 {
+		t, err := time.Parse(time.RFC1123, cr.Header["Last-Modified"][0])
+		if err != nil {
+			return ch, err
+		}
+		ch.LastModified = t
+	}
+
+	return ch, nil
+}
+
+// UpdateHeader represents the headers returned in the response from a Update request.
+type UpdateHeader struct {
+	ContentLength int64     `mapstructure:"Content-Length"`
+	ContentType   string    `mapstructure:"Content-Type"`
+	Date          time.Time `mapstructure:"-"`
+	TransID       string    `mapstructure:"X-Trans-Id"`
+}
+
 // UpdateResult represents the result of an update operation.
 type UpdateResult struct {
 	gophercloud.HeaderResult
 }
 
+// Extract will return a struct of headers returned from a call to Update. To obtain
+// a map of headers, call the ExtractHeader method on the UpdateResult.
+func (ur UpdateResult) Extract() (UpdateHeader, error) {
+	var uh UpdateHeader
+	if ur.Err != nil {
+		return uh, ur.Err
+	}
+
+	if err := mapstructure.Decode(ur.Header, &uh); err != nil {
+		return uh, err
+	}
+
+	if date, ok := ur.Header["Date"]; ok && len(date) > 0 {
+		t, err := time.Parse(time.RFC1123, ur.Header["Date"][0])
+		if err != nil {
+			return uh, err
+		}
+		uh.Date = t
+	}
+
+	return uh, nil
+}
+
+// DeleteHeader represents the headers returned in the response from a Delete request.
+type DeleteHeader struct {
+	ContentLength int64     `mapstructure:"Content-Length"`
+	ContentType   string    `mapstructure:"Content-Type"`
+	Date          time.Time `mapstructure:"-"`
+	TransID       string    `mapstructure:"X-Trans-Id"`
+}
+
 // DeleteResult represents the result of a delete operation.
 type DeleteResult struct {
 	gophercloud.HeaderResult
 }
 
+// Extract will return a struct of headers returned from a call to Delete. To obtain
+// a map of headers, call the ExtractHeader method on the DeleteResult.
+func (dr DeleteResult) Extract() (DeleteHeader, error) {
+	var dh DeleteHeader
+	if dr.Err != nil {
+		return dh, dr.Err
+	}
+
+	if err := mapstructure.Decode(dr.Header, &dh); err != nil {
+		return dh, err
+	}
+
+	if date, ok := dr.Header["Date"]; ok && len(date) > 0 {
+		t, err := time.Parse(time.RFC1123, dr.Header["Date"][0])
+		if err != nil {
+			return dh, err
+		}
+		dh.Date = t
+	}
+
+	return dh, nil
+}
+
+// CopyHeader represents the headers returned in the response from a Copy request.
+type CopyHeader struct {
+	ContentLength          int64     `mapstructure:"Content-Length"`
+	ContentType            string    `mapstructure:"Content-Type"`
+	CopiedFrom             string    `mapstructure:"X-Copied-From"`
+	CopiedFromLastModified time.Time `mapstructure:"-"`
+	Date                   time.Time `mapstructure:"-"`
+	ETag                   string    `mapstructure:"Etag"`
+	LastModified           time.Time `mapstructure:"-"`
+	TransID                string    `mapstructure:"X-Trans-Id"`
+}
+
 // CopyResult represents the result of a copy operation.
 type CopyResult struct {
 	gophercloud.HeaderResult
 }
+
+// Extract will return a struct of headers returned from a call to Copy. To obtain
+// a map of headers, call the ExtractHeader method on the CopyResult.
+func (cr CopyResult) Extract() (CopyHeader, error) {
+	var ch CopyHeader
+	if cr.Err != nil {
+		return ch, cr.Err
+	}
+
+	if err := mapstructure.Decode(cr.Header, &ch); err != nil {
+		return ch, err
+	}
+
+	if date, ok := cr.Header["Date"]; ok && len(date) > 0 {
+		t, err := time.Parse(time.RFC1123, cr.Header["Date"][0])
+		if err != nil {
+			return ch, err
+		}
+		ch.Date = t
+	}
+
+	if date, ok := cr.Header["Last-Modified"]; ok && len(date) > 0 {
+		t, err := time.Parse(time.RFC1123, cr.Header["Last-Modified"][0])
+		if err != nil {
+			return ch, err
+		}
+		ch.LastModified = t
+	}
+
+	if date, ok := cr.Header["X-Copied-From-Last-Modified"]; ok && len(date) > 0 {
+		t, err := time.Parse(time.RFC1123, cr.Header["X-Copied-From-Last-Modified"][0])
+		if err != nil {
+			return ch, err
+		}
+		ch.CopiedFromLastModified = t
+	}
+
+	return ch, nil
+}