More specific types for ObjectStorage response object fields (#74)

* more accurate types for objectstorage response object fields (e.g. ContentLength: string -> in64)

* containers unit tests for new field types

* more specific types for accounts headers fields

* update accounts unit tests

* download header unmarshal method and unit test

* object results unmarshal methods
diff --git a/openstack/objectstorage/v1/objects/results.go b/openstack/objectstorage/v1/objects/results.go
index 3cfe1f4..1390faa 100644
--- a/openstack/objectstorage/v1/objects/results.go
+++ b/openstack/objectstorage/v1/objects/results.go
@@ -1,9 +1,11 @@
 package objects
 
 import (
+	"encoding/json"
 	"fmt"
 	"io"
 	"io/ioutil"
+	"strconv"
 	"strings"
 
 	"github.com/gophercloud/gophercloud"
@@ -24,7 +26,7 @@
 	// LastModified is the RFC3339Milli time the object was last modified, represented
 	// as a string. For any given object (obj), this value may be parsed to a time.Time:
 	// lastModified, err := time.Parse(gophercloud.RFC3339Milli, obj.LastModified)
-	LastModified string `json:"last_modified"`
+	LastModified gophercloud.JSONRFC1123 `json:"last_modified"`
 
 	// Name is the unique name for the object.
 	Name string `json:"name"`
@@ -101,7 +103,7 @@
 	AcceptRanges       string                  `json:"Accept-Ranges"`
 	ContentDisposition string                  `json:"Content-Disposition"`
 	ContentEncoding    string                  `json:"Content-Encoding"`
-	ContentLength      string                  `json:"Content-Length"`
+	ContentLength      int64                   `json:"-"`
 	ContentType        string                  `json:"Content-Type"`
 	Date               gophercloud.JSONRFC1123 `json:"Date"`
 	DeleteAt           gophercloud.JSONUnix    `json:"X-Delete-At"`
@@ -112,6 +114,32 @@
 	TransID            string                  `json:"X-Trans-Id"`
 }
 
+func (h *DownloadHeader) UnmarshalJSON(b []byte) error {
+	type tmp DownloadHeader
+	var hTmp *struct {
+		tmp
+		ContentLength string `json:"Content-Length"`
+	}
+	err := json.Unmarshal(b, &hTmp)
+	if err != nil {
+		return err
+	}
+
+	*h = DownloadHeader(hTmp.tmp)
+
+	switch hTmp.ContentLength {
+	case "":
+		h.ContentLength = 0
+	default:
+		h.ContentLength, err = strconv.ParseInt(hTmp.ContentLength, 10, 64)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
 // DownloadResult is a *http.Response that is returned from a call to the Download function.
 type DownloadResult struct {
 	gophercloud.HeaderResult
@@ -148,7 +176,7 @@
 type GetHeader struct {
 	ContentDisposition string                  `json:"Content-Disposition"`
 	ContentEncoding    string                  `json:"Content-Encoding"`
-	ContentLength      string                  `json:"Content-Length"`
+	ContentLength      int64                   `json:"Content-Length"`
 	ContentType        string                  `json:"Content-Type"`
 	Date               gophercloud.JSONRFC1123 `json:"Date"`
 	DeleteAt           gophercloud.JSONUnix    `json:"X-Delete-At"`
@@ -159,6 +187,32 @@
 	TransID            string                  `json:"X-Trans-Id"`
 }
 
+func (h *GetHeader) UnmarshalJSON(b []byte) error {
+	type tmp GetHeader
+	var hTmp *struct {
+		tmp
+		ContentLength string `json:"Content-Length"`
+	}
+	err := json.Unmarshal(b, &hTmp)
+	if err != nil {
+		return err
+	}
+
+	*h = GetHeader(hTmp.tmp)
+
+	switch hTmp.ContentLength {
+	case "":
+		h.ContentLength = 0
+	default:
+		h.ContentLength, err = strconv.ParseInt(hTmp.ContentLength, 10, 64)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
 // GetResult is a *http.Response that is returned from a call to the Get function.
 type GetResult struct {
 	gophercloud.HeaderResult
@@ -190,7 +244,7 @@
 
 // CreateHeader represents the headers returned in the response from a Create request.
 type CreateHeader struct {
-	ContentLength string                  `json:"Content-Length"`
+	ContentLength int64                   `json:"Content-Length"`
 	ContentType   string                  `json:"Content-Type"`
 	Date          gophercloud.JSONRFC1123 `json:"Date"`
 	ETag          string                  `json:"Etag"`
@@ -198,6 +252,32 @@
 	TransID       string                  `json:"X-Trans-Id"`
 }
 
+func (h *CreateHeader) UnmarshalJSON(b []byte) error {
+	type tmp CreateHeader
+	var hTmp *struct {
+		tmp
+		ContentLength string `json:"Content-Length"`
+	}
+	err := json.Unmarshal(b, &hTmp)
+	if err != nil {
+		return err
+	}
+
+	*h = CreateHeader(hTmp.tmp)
+
+	switch hTmp.ContentLength {
+	case "":
+		h.ContentLength = 0
+	default:
+		h.ContentLength, err = strconv.ParseInt(hTmp.ContentLength, 10, 64)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
 // CreateResult represents the result of a create operation.
 type CreateResult struct {
 	checksum string
@@ -217,12 +297,38 @@
 
 // UpdateHeader represents the headers returned in the response from a Update request.
 type UpdateHeader struct {
-	ContentLength string                  `json:"Content-Length"`
+	ContentLength int64                   `json:"Content-Length"`
 	ContentType   string                  `json:"Content-Type"`
 	Date          gophercloud.JSONRFC1123 `json:"Date"`
 	TransID       string                  `json:"X-Trans-Id"`
 }
 
+func (h *UpdateHeader) UnmarshalJSON(b []byte) error {
+	type tmp UpdateHeader
+	var hTmp *struct {
+		tmp
+		ContentLength string `json:"Content-Length"`
+	}
+	err := json.Unmarshal(b, &hTmp)
+	if err != nil {
+		return err
+	}
+
+	*h = UpdateHeader(hTmp.tmp)
+
+	switch hTmp.ContentLength {
+	case "":
+		h.ContentLength = 0
+	default:
+		h.ContentLength, err = strconv.ParseInt(hTmp.ContentLength, 10, 64)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
 // UpdateResult represents the result of an update operation.
 type UpdateResult struct {
 	gophercloud.HeaderResult
@@ -238,12 +344,38 @@
 
 // DeleteHeader represents the headers returned in the response from a Delete request.
 type DeleteHeader struct {
-	ContentLength string                  `json:"Content-Length"`
+	ContentLength int64                   `json:"Content-Length"`
 	ContentType   string                  `json:"Content-Type"`
 	Date          gophercloud.JSONRFC1123 `json:"Date"`
 	TransID       string                  `json:"X-Trans-Id"`
 }
 
+func (h *DeleteHeader) UnmarshalJSON(b []byte) error {
+	type tmp DeleteHeader
+	var hTmp *struct {
+		tmp
+		ContentLength string `json:"Content-Length"`
+	}
+	err := json.Unmarshal(b, &hTmp)
+	if err != nil {
+		return err
+	}
+
+	*h = DeleteHeader(hTmp.tmp)
+
+	switch hTmp.ContentLength {
+	case "":
+		h.ContentLength = 0
+	default:
+		h.ContentLength, err = strconv.ParseInt(hTmp.ContentLength, 10, 64)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
 // DeleteResult represents the result of a delete operation.
 type DeleteResult struct {
 	gophercloud.HeaderResult
@@ -269,6 +401,32 @@
 	TransID                string                  `json:"X-Trans-Id"`
 }
 
+func (h *CopyHeader) UnmarshalJSON(b []byte) error {
+	type tmp CopyHeader
+	var hTmp *struct {
+		tmp
+		ContentLength string `json:"Content-Length"`
+	}
+	err := json.Unmarshal(b, &hTmp)
+	if err != nil {
+		return err
+	}
+
+	*h = CopyHeader(hTmp.tmp)
+
+	switch hTmp.ContentLength {
+	case "":
+		h.ContentLength = 0
+	default:
+		h.ContentLength, err = strconv.ParseInt(hTmp.ContentLength, 10, 64)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
 // CopyResult represents the result of a copy operation.
 type CopyResult struct {
 	gophercloud.HeaderResult