remove mapstructure from identity,networking,objectstorage,orchestration,pagination
diff --git a/openstack/orchestration/v1/apiversions/results.go b/openstack/orchestration/v1/apiversions/results.go
index 0373ccc..a7c22a2 100644
--- a/openstack/orchestration/v1/apiversions/results.go
+++ b/openstack/orchestration/v1/apiversions/results.go
@@ -1,7 +1,6 @@
 package apiversions
 
 import (
-	"github.com/mitchellh/mapstructure"
 	"github.com/gophercloud/gophercloud"
 	"github.com/gophercloud/gophercloud/pagination"
 )
@@ -9,9 +8,9 @@
 // APIVersion represents an API version for Neutron. It contains the status of
 // the API, and its unique ID.
 type APIVersion struct {
-	Status string             `mapstructure:"status"`
-	ID     string             `mapstructure:"id"`
-	Links  []gophercloud.Link `mapstructure:"links"`
+	Status string             `json:"status"`
+	ID     string             `json:"id"`
+	Links  []gophercloud.Link `json:"links"`
 }
 
 // APIVersionPage is the page returned by a pager when traversing over a
@@ -23,20 +22,15 @@
 // IsEmpty checks whether an APIVersionPage struct is empty.
 func (r APIVersionPage) IsEmpty() (bool, error) {
 	is, err := ExtractAPIVersions(r)
-	if err != nil {
-		return true, err
-	}
-	return len(is) == 0, nil
+	return len(is) == 0, err
 }
 
 // ExtractAPIVersions takes a collection page, extracts all of the elements,
 // and returns them a slice of APIVersion structs. It is effectively a cast.
-func ExtractAPIVersions(page pagination.Page) ([]APIVersion, error) {
-	var resp struct {
-		Versions []APIVersion `mapstructure:"versions"`
+func ExtractAPIVersions(r pagination.Page) ([]APIVersion, error) {
+	var s struct {
+		APIVersions []APIVersion `json:"versions"`
 	}
-
-	err := mapstructure.Decode(page.(APIVersionPage).Body, &resp)
-
-	return resp.Versions, err
+	err := (r.(APIVersionPage)).ExtractInto(&s)
+	return s.APIVersions, err
 }
diff --git a/openstack/orchestration/v1/buildinfo/results.go b/openstack/orchestration/v1/buildinfo/results.go
index fe655a3..c3d2cdb 100644
--- a/openstack/orchestration/v1/buildinfo/results.go
+++ b/openstack/orchestration/v1/buildinfo/results.go
@@ -1,19 +1,18 @@
 package buildinfo
 
 import (
-	"github.com/mitchellh/mapstructure"
 	"github.com/gophercloud/gophercloud"
 )
 
 // Revision represents the API/Engine revision of a Heat deployment.
 type Revision struct {
-	Revision string `mapstructure:"revision"`
+	Revision string `json:"revision"`
 }
 
 // BuildInfo represents the build information for a Heat deployment.
 type BuildInfo struct {
-	API    Revision `mapstructure:"api"`
-	Engine Revision `mapstructure:"engine"`
+	API    Revision `json:"api"`
+	Engine Revision `json:"engine"`
 }
 
 // GetResult represents the result of a Get operation.
@@ -24,14 +23,7 @@
 // Extract returns a pointer to a BuildInfo object and is called after a
 // Get operation.
 func (r GetResult) Extract() (*BuildInfo, error) {
-	if r.Err != nil {
-		return nil, r.Err
-	}
-
-	var res BuildInfo
-	if err := mapstructure.Decode(r.Body, &res); err != nil {
-		return nil, err
-	}
-
-	return &res, nil
+	var s *BuildInfo
+	err := r.ExtractInto(&s)
+	return s, err
 }
diff --git a/openstack/orchestration/v1/stackevents/fixtures.go b/openstack/orchestration/v1/stackevents/fixtures.go
index b6ac274..48524e5 100644
--- a/openstack/orchestration/v1/stackevents/fixtures.go
+++ b/openstack/orchestration/v1/stackevents/fixtures.go
@@ -15,7 +15,7 @@
 var FindExpected = []Event{
 	Event{
 		ResourceName: "hello_world",
-		Time:         time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC),
+		Time:         gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC)),
 		Links: []gophercloud.Link{
 			gophercloud.Link{
 				Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/06feb26f-9298-4a9b-8749-9d770e5d577a",
@@ -38,7 +38,7 @@
 	},
 	Event{
 		ResourceName: "hello_world",
-		Time:         time.Date(2015, 2, 5, 21, 33, 27, 0, time.UTC),
+		Time:         gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 5, 21, 33, 27, 0, time.UTC)),
 		Links: []gophercloud.Link{
 			gophercloud.Link{
 				Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/93940999-7d40-44ae-8de4-19624e7b8d18",
@@ -132,7 +132,7 @@
 var ListExpected = []Event{
 	Event{
 		ResourceName: "hello_world",
-		Time:         time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC),
+		Time:         gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC)),
 		Links: []gophercloud.Link{
 			gophercloud.Link{
 				Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/06feb26f-9298-4a9b-8749-9d770e5d577a",
@@ -155,7 +155,7 @@
 	},
 	Event{
 		ResourceName: "hello_world",
-		Time:         time.Date(2015, 2, 5, 21, 33, 27, 0, time.UTC),
+		Time:         gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 5, 21, 33, 27, 0, time.UTC)),
 		Links: []gophercloud.Link{
 			gophercloud.Link{
 				Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/93940999-7d40-44ae-8de4-19624e7b8d18",
@@ -257,7 +257,7 @@
 var ListResourceEventsExpected = []Event{
 	Event{
 		ResourceName: "hello_world",
-		Time:         time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC),
+		Time:         gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC)),
 		Links: []gophercloud.Link{
 			gophercloud.Link{
 				Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/06feb26f-9298-4a9b-8749-9d770e5d577a",
@@ -280,7 +280,7 @@
 	},
 	Event{
 		ResourceName: "hello_world",
-		Time:         time.Date(2015, 2, 5, 21, 33, 27, 0, time.UTC),
+		Time:         gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 5, 21, 33, 27, 0, time.UTC)),
 		Links: []gophercloud.Link{
 			gophercloud.Link{
 				Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/93940999-7d40-44ae-8de4-19624e7b8d18",
@@ -381,7 +381,7 @@
 // GetExpected represents the expected object from a Get request.
 var GetExpected = &Event{
 	ResourceName: "hello_world",
-	Time:         time.Date(2015, 2, 5, 21, 33, 27, 0, time.UTC),
+	Time:         gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 5, 21, 33, 27, 0, time.UTC)),
 	Links: []gophercloud.Link{
 		gophercloud.Link{
 			Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/93940999-7d40-44ae-8de4-19624e7b8d18",
diff --git a/openstack/orchestration/v1/stackevents/results.go b/openstack/orchestration/v1/stackevents/results.go
index ac94bb5..6c7f183 100644
--- a/openstack/orchestration/v1/stackevents/results.go
+++ b/openstack/orchestration/v1/stackevents/results.go
@@ -1,11 +1,6 @@
 package stackevents
 
 import (
-	"fmt"
-	"reflect"
-	"time"
-
-	"github.com/mitchellh/mapstructure"
 	"github.com/gophercloud/gophercloud"
 	"github.com/gophercloud/gophercloud/pagination"
 )
@@ -13,23 +8,23 @@
 // Event represents a stack event.
 type Event struct {
 	// The name of the resource for which the event occurred.
-	ResourceName string `mapstructure:"resource_name"`
+	ResourceName string `json:"resource_name"`
 	// The time the event occurred.
-	Time time.Time `mapstructure:"-"`
+	Time gophercloud.JSONRFC3339NoZ `json:"event_time"`
 	// The URLs to the event.
-	Links []gophercloud.Link `mapstructure:"links"`
+	Links []gophercloud.Link `json:"links"`
 	// The logical ID of the stack resource.
-	LogicalResourceID string `mapstructure:"logical_resource_id"`
+	LogicalResourceID string `json:"logical_resource_id"`
 	// The reason of the status of the event.
-	ResourceStatusReason string `mapstructure:"resource_status_reason"`
+	ResourceStatusReason string `json:"resource_status_reason"`
 	// The status of the event.
-	ResourceStatus string `mapstructure:"resource_status"`
+	ResourceStatus string `json:"resource_status"`
 	// The physical ID of the stack resource.
-	PhysicalResourceID string `mapstructure:"physical_resource_id"`
+	PhysicalResourceID string `json:"physical_resource_id"`
 	// The event ID.
-	ID string `mapstructure:"id"`
+	ID string `json:"id"`
 	// Properties of the stack resource.
-	ResourceProperties map[string]interface{} `mapstructure:"resource_properties"`
+	ResourceProperties map[string]interface{} `json:"resource_properties"`
 }
 
 // FindResult represents the result of a Find operation.
@@ -40,32 +35,11 @@
 // Extract returns a slice of Event objects and is called after a
 // Find operation.
 func (r FindResult) Extract() ([]Event, error) {
-	if r.Err != nil {
-		return nil, r.Err
+	var s struct {
+		Events []Event `json:"events"`
 	}
-
-	var res struct {
-		Res []Event `mapstructure:"events"`
-	}
-
-	if err := mapstructure.Decode(r.Body, &res); err != nil {
-		return nil, err
-	}
-
-	events := r.Body.(map[string]interface{})["events"].([]interface{})
-
-	for i, eventRaw := range events {
-		event := eventRaw.(map[string]interface{})
-		if date, ok := event["event_time"]; ok && date != nil {
-			t, err := time.Parse(gophercloud.StackFmtTime, date.(string))
-			if err != nil {
-				return nil, err
-			}
-			res.Res[i].Time = t
-		}
-	}
-
-	return res.Res, nil
+	err := r.ExtractInto(&s)
+	return s.Events, err
 }
 
 // EventPage abstracts the raw results of making a List() request against the API.
@@ -78,10 +52,7 @@
 // IsEmpty returns true if a page contains no Server results.
 func (r EventPage) IsEmpty() (bool, error) {
 	events, err := ExtractEvents(r)
-	if err != nil {
-		return true, err
-	}
-	return len(events) == 0, nil
+	return len(events) == 0, err
 }
 
 // LastMarker returns the last stack ID in a ListResult.
@@ -97,39 +68,12 @@
 }
 
 // ExtractEvents interprets the results of a single page from a List() call, producing a slice of Event entities.
-func ExtractEvents(page pagination.Page) ([]Event, error) {
-	casted := page.(EventPage).Body
-
-	var res struct {
-		Res []Event `mapstructure:"events"`
+func ExtractEvents(r pagination.Page) ([]Event, error) {
+	var s struct {
+		Events []Event `json:"events"`
 	}
-
-	if err := mapstructure.Decode(casted, &res); err != nil {
-		return nil, err
-	}
-
-	var events []interface{}
-	switch casted.(type) {
-	case map[string]interface{}:
-		events = casted.(map[string]interface{})["events"].([]interface{})
-	case map[string][]interface{}:
-		events = casted.(map[string][]interface{})["events"]
-	default:
-		return res.Res, fmt.Errorf("Unknown type: %v", reflect.TypeOf(casted))
-	}
-
-	for i, eventRaw := range events {
-		event := eventRaw.(map[string]interface{})
-		if date, ok := event["event_time"]; ok && date != nil {
-			t, err := time.Parse(gophercloud.StackFmtTime, date.(string))
-			if err != nil {
-				return nil, err
-			}
-			res.Res[i].Time = t
-		}
-	}
-
-	return res.Res, nil
+	err := (r.(EventPage)).ExtractInto(&s)
+	return s.Events, err
 }
 
 // ExtractResourceEvents interprets the results of a single page from a
@@ -146,27 +90,9 @@
 // Extract returns a pointer to an Event object and is called after a
 // Get operation.
 func (r GetResult) Extract() (*Event, error) {
-	if r.Err != nil {
-		return nil, r.Err
+	var s struct {
+		Event *Event `json:"event"`
 	}
-
-	var res struct {
-		Res *Event `mapstructure:"event"`
-	}
-
-	if err := mapstructure.Decode(r.Body, &res); err != nil {
-		return nil, err
-	}
-
-	event := r.Body.(map[string]interface{})["event"].(map[string]interface{})
-
-	if date, ok := event["event_time"]; ok && date != nil {
-		t, err := time.Parse(gophercloud.StackFmtTime, date.(string))
-		if err != nil {
-			return nil, err
-		}
-		res.Res.Time = t
-	}
-
-	return res.Res, nil
+	err := r.ExtractInto(&s)
+	return s.Event, err
 }
diff --git a/openstack/orchestration/v1/stackresources/fixtures.go b/openstack/orchestration/v1/stackresources/fixtures.go
index cdf1f3c..a622f7f 100644
--- a/openstack/orchestration/v1/stackresources/fixtures.go
+++ b/openstack/orchestration/v1/stackresources/fixtures.go
@@ -27,8 +27,8 @@
 		},
 		LogicalID:    "hello_world",
 		StatusReason: "state changed",
-		UpdatedTime:  time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC),
-		CreationTime: time.Date(2015, 2, 5, 21, 33, 10, 0, time.UTC),
+		UpdatedTime:  gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC)),
+		CreationTime: gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 5, 21, 33, 10, 0, time.UTC)),
 		RequiredBy:   []interface{}{},
 		Status:       "CREATE_IN_PROGRESS",
 		PhysicalID:   "49181cd6-169a-4130-9455-31185bbfc5bf",
@@ -98,8 +98,8 @@
 		},
 		LogicalID:    "hello_world",
 		StatusReason: "state changed",
-		UpdatedTime:  time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC),
-		CreationTime: time.Date(2015, 2, 5, 21, 33, 10, 0, time.UTC),
+		UpdatedTime:  gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC)),
+		CreationTime: gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 5, 21, 33, 10, 0, time.UTC)),
 		RequiredBy:   []interface{}{},
 		Status:       "CREATE_IN_PROGRESS",
 		PhysicalID:   "49181cd6-169a-4130-9455-31185bbfc5bf",
@@ -176,7 +176,7 @@
 	LogicalID:    "wordpress_instance",
 	Attributes:   map[string]interface{}{"SXSW": "atx"},
 	StatusReason: "state changed",
-	UpdatedTime:  time.Date(2014, 12, 10, 18, 34, 35, 0, time.UTC),
+	UpdatedTime:  gophercloud.JSONRFC3339NoZ(time.Date(2014, 12, 10, 18, 34, 35, 0, time.UTC)),
 	RequiredBy:   []interface{}{},
 	Status:       "CREATE_COMPLETE",
 	PhysicalID:   "00e3a2fe-c65d-403c-9483-4db9930dd194",
diff --git a/openstack/orchestration/v1/stackresources/results.go b/openstack/orchestration/v1/stackresources/results.go
index edbd34f..951f144 100644
--- a/openstack/orchestration/v1/stackresources/results.go
+++ b/openstack/orchestration/v1/stackresources/results.go
@@ -2,29 +2,25 @@
 
 import (
 	"encoding/json"
-	"fmt"
-	"reflect"
-	"time"
 
-	"github.com/mitchellh/mapstructure"
 	"github.com/gophercloud/gophercloud"
 	"github.com/gophercloud/gophercloud/pagination"
 )
 
 // Resource represents a stack resource.
 type Resource struct {
-	Attributes   map[string]interface{} `mapstructure:"attributes"`
-	CreationTime time.Time              `mapstructure:"-"`
-	Description  string                 `mapstructure:"description"`
-	Links        []gophercloud.Link     `mapstructure:"links"`
-	LogicalID    string                 `mapstructure:"logical_resource_id"`
-	Name         string                 `mapstructure:"resource_name"`
-	PhysicalID   string                 `mapstructure:"physical_resource_id"`
-	RequiredBy   []interface{}          `mapstructure:"required_by"`
-	Status       string                 `mapstructure:"resource_status"`
-	StatusReason string                 `mapstructure:"resource_status_reason"`
-	Type         string                 `mapstructure:"resource_type"`
-	UpdatedTime  time.Time              `mapstructure:"-"`
+	Attributes   map[string]interface{}     `json:"attributes"`
+	CreationTime gophercloud.JSONRFC3339NoZ `json:"creation_time"`
+	Description  string                     `json:"description"`
+	Links        []gophercloud.Link         `json:"links"`
+	LogicalID    string                     `json:"logical_resource_id"`
+	Name         string                     `json:"resource_name"`
+	PhysicalID   string                     `json:"physical_resource_id"`
+	RequiredBy   []interface{}              `json:"required_by"`
+	Status       string                     `json:"resource_status"`
+	StatusReason string                     `json:"resource_status_reason"`
+	Type         string                     `json:"resource_type"`
+	UpdatedTime  gophercloud.JSONRFC3339NoZ `json:"updated_time"`
 }
 
 // FindResult represents the result of a Find operation.
@@ -35,39 +31,11 @@
 // Extract returns a slice of Resource objects and is called after a
 // Find operation.
 func (r FindResult) Extract() ([]Resource, error) {
-	if r.Err != nil {
-		return nil, r.Err
+	var s struct {
+		Resources []Resource `json:"resources"`
 	}
-
-	var res struct {
-		Res []Resource `mapstructure:"resources"`
-	}
-
-	if err := mapstructure.Decode(r.Body, &res); err != nil {
-		return nil, err
-	}
-
-	resources := r.Body.(map[string]interface{})["resources"].([]interface{})
-
-	for i, resourceRaw := range resources {
-		resource := resourceRaw.(map[string]interface{})
-		if date, ok := resource["updated_time"]; ok && date != nil {
-			t, err := time.Parse(gophercloud.StackFmtTime, date.(string))
-			if err != nil {
-				return nil, err
-			}
-			res.Res[i].UpdatedTime = t
-		}
-		if date, ok := resource["creation_time"]; ok && date != nil {
-			t, err := time.Parse(gophercloud.StackFmtTime, date.(string))
-			if err != nil {
-				return nil, err
-			}
-			res.Res[i].CreationTime = t
-		}
-	}
-
-	return res.Res, nil
+	err := r.ExtractInto(&s)
+	return s.Resources, err
 }
 
 // ResourcePage abstracts the raw results of making a List() request against the API.
@@ -80,51 +48,16 @@
 // IsEmpty returns true if a page contains no Server results.
 func (r ResourcePage) IsEmpty() (bool, error) {
 	resources, err := ExtractResources(r)
-	if err != nil {
-		return true, err
-	}
-	return len(resources) == 0, nil
+	return len(resources) == 0, err
 }
 
 // ExtractResources interprets the results of a single page from a List() call, producing a slice of Resource entities.
-func ExtractResources(page pagination.Page) ([]Resource, error) {
-	casted := page.(ResourcePage).Body
-
-	var response struct {
-		Resources []Resource `mapstructure:"resources"`
+func ExtractResources(r pagination.Page) ([]Resource, error) {
+	var s struct {
+		Resources []Resource `json:"resources"`
 	}
-	if err := mapstructure.Decode(casted, &response); err != nil {
-		return nil, err
-	}
-	var resources []interface{}
-	switch casted.(type) {
-	case map[string]interface{}:
-		resources = casted.(map[string]interface{})["resources"].([]interface{})
-	case map[string][]interface{}:
-		resources = casted.(map[string][]interface{})["resources"]
-	default:
-		return response.Resources, fmt.Errorf("Unknown type: %v", reflect.TypeOf(casted))
-	}
-
-	for i, resourceRaw := range resources {
-		resource := resourceRaw.(map[string]interface{})
-		if date, ok := resource["updated_time"]; ok && date != nil {
-			t, err := time.Parse(gophercloud.StackFmtTime, date.(string))
-			if err != nil {
-				return nil, err
-			}
-			response.Resources[i].UpdatedTime = t
-		}
-		if date, ok := resource["creation_time"]; ok && date != nil {
-			t, err := time.Parse(gophercloud.StackFmtTime, date.(string))
-			if err != nil {
-				return nil, err
-			}
-			response.Resources[i].CreationTime = t
-		}
-	}
-
-	return response.Resources, nil
+	err := (r.(ResourcePage)).ExtractInto(&s)
+	return s.Resources, err
 }
 
 // GetResult represents the result of a Get operation.
@@ -135,36 +68,11 @@
 // Extract returns a pointer to a Resource object and is called after a
 // Get operation.
 func (r GetResult) Extract() (*Resource, error) {
-	if r.Err != nil {
-		return nil, r.Err
+	var s struct {
+		Resource *Resource `json:"resource"`
 	}
-
-	var res struct {
-		Res *Resource `mapstructure:"resource"`
-	}
-
-	if err := mapstructure.Decode(r.Body, &res); err != nil {
-		return nil, err
-	}
-
-	resource := r.Body.(map[string]interface{})["resource"].(map[string]interface{})
-
-	if date, ok := resource["updated_time"]; ok && date != nil {
-		t, err := time.Parse(gophercloud.StackFmtTime, date.(string))
-		if err != nil {
-			return nil, err
-		}
-		res.Res.UpdatedTime = t
-	}
-	if date, ok := resource["creation_time"]; ok && date != nil {
-		t, err := time.Parse(gophercloud.StackFmtTime, date.(string))
-		if err != nil {
-			return nil, err
-		}
-		res.Res.CreationTime = t
-	}
-
-	return res.Res, nil
+	err := r.ExtractInto(&s)
+	return s.Resource, err
 }
 
 // MetadataResult represents the result of a Metadata operation.
@@ -175,19 +83,11 @@
 // Extract returns a map object and is called after a
 // Metadata operation.
 func (r MetadataResult) Extract() (map[string]string, error) {
-	if r.Err != nil {
-		return nil, r.Err
+	var s struct {
+		Meta map[string]string `json:"metadata"`
 	}
-
-	var res struct {
-		Meta map[string]string `mapstructure:"metadata"`
-	}
-
-	if err := mapstructure.Decode(r.Body, &res); err != nil {
-		return nil, err
-	}
-
-	return res.Meta, nil
+	err := r.ExtractInto(&s)
+	return s.Meta, err
 }
 
 // ResourceTypePage abstracts the raw results of making a ListTypes() request against the API.
@@ -200,10 +100,7 @@
 // IsEmpty returns true if a ResourceTypePage contains no resource types.
 func (r ResourceTypePage) IsEmpty() (bool, error) {
 	rts, err := ExtractResourceTypes(r)
-	if err != nil {
-		return true, err
-	}
-	return len(rts) == 0, nil
+	return len(rts) == 0, err
 }
 
 // ResourceTypes represents the type that holds the result of ExtractResourceTypes.
@@ -223,25 +120,20 @@
 }
 
 // ExtractResourceTypes extracts and returns resource types.
-func ExtractResourceTypes(page pagination.Page) (ResourceTypes, error) {
-	casted := page.(ResourceTypePage).Body
-
-	var response struct {
-		ResourceTypes ResourceTypes `mapstructure:"resource_types"`
+func ExtractResourceTypes(r pagination.Page) (ResourceTypes, error) {
+	var s struct {
+		ResourceTypes ResourceTypes `json:"resource_types"`
 	}
-
-	if err := mapstructure.Decode(casted, &response); err != nil {
-		return nil, err
-	}
-	return response.ResourceTypes, nil
+	err := (r.(ResourceTypePage)).ExtractInto(&s)
+	return s.ResourceTypes, err
 }
 
 // TypeSchema represents a stack resource schema.
 type TypeSchema struct {
-	Attributes    map[string]interface{} `mapstructure:"attributes"`
-	Properties    map[string]interface{} `mapstrucutre:"properties"`
-	ResourceType  string                 `mapstructure:"resource_type"`
-	SupportStatus map[string]interface{} `mapstructure:"support_status"`
+	Attributes    map[string]interface{} `json:"attributes"`
+	Properties    map[string]interface{} `json:"properties"`
+	ResourceType  string                 `json:"resource_type"`
+	SupportStatus map[string]interface{} `json:"support_status"`
 }
 
 // SchemaResult represents the result of a Schema operation.
@@ -252,17 +144,9 @@
 // Extract returns a pointer to a TypeSchema object and is called after a
 // Schema operation.
 func (r SchemaResult) Extract() (*TypeSchema, error) {
-	if r.Err != nil {
-		return nil, r.Err
-	}
-
-	var res TypeSchema
-
-	if err := mapstructure.Decode(r.Body, &res); err != nil {
-		return nil, err
-	}
-
-	return &res, nil
+	var s *TypeSchema
+	err := r.ExtractInto(&s)
+	return s, err
 }
 
 // TemplateResult represents the result of a Template operation.
diff --git a/openstack/orchestration/v1/stacks/fixtures.go b/openstack/orchestration/v1/stacks/fixtures.go
index 49e4168..f1d66f4 100644
--- a/openstack/orchestration/v1/stacks/fixtures.go
+++ b/openstack/orchestration/v1/stacks/fixtures.go
@@ -60,7 +60,7 @@
 		},
 		StatusReason: "Stack CREATE completed successfully",
 		Name:         "postman_stack",
-		CreationTime: time.Date(2015, 2, 3, 20, 7, 39, 0, time.UTC),
+		CreationTime: gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 3, 20, 7, 39, 0, time.UTC)),
 		Status:       "CREATE_COMPLETE",
 		ID:           "16ef0584-4458-41eb-87c8-0dc8d5f66c87",
 		Tags:         []string{"rackspace", "atx"},
@@ -75,8 +75,8 @@
 		},
 		StatusReason: "Stack successfully updated",
 		Name:         "gophercloud-test-stack-2",
-		CreationTime: time.Date(2014, 12, 11, 17, 39, 16, 0, time.UTC),
-		UpdatedTime:  time.Date(2014, 12, 11, 17, 40, 37, 0, time.UTC),
+		CreationTime: gophercloud.JSONRFC3339NoZ(time.Date(2014, 12, 11, 17, 39, 16, 0, time.UTC)),
+		UpdatedTime:  gophercloud.JSONRFC3339NoZ(time.Date(2014, 12, 11, 17, 40, 37, 0, time.UTC)),
 		Status:       "UPDATE_COMPLETE",
 		ID:           "db6977b2-27aa-4775-9ae7-6213212d4ada",
 		Tags:         []string{"sfo", "satx"},
@@ -157,7 +157,7 @@
 	StatusReason: "Stack CREATE completed successfully",
 	Name:         "postman_stack",
 	Outputs:      []map[string]interface{}{},
-	CreationTime: time.Date(2015, 2, 3, 20, 7, 39, 0, time.UTC),
+	CreationTime: gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 3, 20, 7, 39, 0, time.UTC)),
 	Links: []gophercloud.Link{
 		gophercloud.Link{
 			Href: "http://166.76.160.117:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/16ef0584-4458-41eb-87c8-0dc8d5f66c87",
@@ -255,7 +255,7 @@
 		"OS::stack_id":   "16ef0584-4458-41eb-87c8-0dc8d5f66c87",
 	},
 	Name:         "postman_stack",
-	CreationTime: time.Date(2015, 2, 3, 20, 7, 39, 0, time.UTC),
+	CreationTime: gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 3, 20, 7, 39, 0, time.UTC)),
 	Links: []gophercloud.Link{
 		gophercloud.Link{
 			Href: "http://166.76.160.117:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/16ef0584-4458-41eb-87c8-0dc8d5f66c87",
diff --git a/openstack/orchestration/v1/stacks/results.go b/openstack/orchestration/v1/stacks/results.go
index 72855ff..5da178e 100644
--- a/openstack/orchestration/v1/stacks/results.go
+++ b/openstack/orchestration/v1/stacks/results.go
@@ -2,19 +2,15 @@
 
 import (
 	"encoding/json"
-	"fmt"
-	"reflect"
-	"time"
 
-	"github.com/mitchellh/mapstructure"
 	"github.com/gophercloud/gophercloud"
 	"github.com/gophercloud/gophercloud/pagination"
 )
 
 // CreatedStack represents the object extracted from a Create operation.
 type CreatedStack struct {
-	ID    string             `mapstructure:"id"`
-	Links []gophercloud.Link `mapstructure:"links"`
+	ID    string             `json:"id"`
+	Links []gophercloud.Link `json:"links"`
 }
 
 // CreateResult represents the result of a Create operation.
@@ -25,19 +21,11 @@
 // Extract returns a pointer to a CreatedStack object and is called after a
 // Create operation.
 func (r CreateResult) Extract() (*CreatedStack, error) {
-	if r.Err != nil {
-		return nil, r.Err
+	var s struct {
+		CreatedStack *CreatedStack `json:"stack"`
 	}
-
-	var res struct {
-		Stack *CreatedStack `mapstructure:"stack"`
-	}
-
-	if err := mapstructure.Decode(r.Body, &res); err != nil {
-		return nil, err
-	}
-
-	return res.Stack, nil
+	err := r.ExtractInto(&s)
+	return s.CreatedStack, err
 }
 
 // AdoptResult represents the result of an Adopt operation. AdoptResult has the
@@ -54,90 +42,50 @@
 // IsEmpty returns true if a ListResult contains no Stacks.
 func (r StackPage) IsEmpty() (bool, error) {
 	stacks, err := ExtractStacks(r)
-	if err != nil {
-		return true, err
-	}
-	return len(stacks) == 0, nil
+	return len(stacks) == 0, err
 }
 
 // ListedStack represents an element in the slice extracted from a List operation.
 type ListedStack struct {
-	CreationTime time.Time          `mapstructure:"-"`
-	Description  string             `mapstructure:"description"`
-	ID           string             `mapstructure:"id"`
-	Links        []gophercloud.Link `mapstructure:"links"`
-	Name         string             `mapstructure:"stack_name"`
-	Status       string             `mapstructure:"stack_status"`
-	StatusReason string             `mapstructure:"stack_status_reason"`
-	Tags         []string           `mapstructure:"tags"`
-	UpdatedTime  time.Time          `mapstructure:"-"`
+	CreationTime gophercloud.JSONRFC3339NoZ `json:"creation_time"`
+	Description  string                     `json:"description"`
+	ID           string                     `json:"id"`
+	Links        []gophercloud.Link         `json:"links"`
+	Name         string                     `json:"stack_name"`
+	Status       string                     `json:"stack_status"`
+	StatusReason string                     `json:"stack_status_reason"`
+	Tags         []string                   `json:"tags"`
+	UpdatedTime  gophercloud.JSONRFC3339NoZ `json:"updated_time"`
 }
 
 // ExtractStacks extracts and returns a slice of ListedStack. It is used while iterating
 // over a stacks.List call.
-func ExtractStacks(page pagination.Page) ([]ListedStack, error) {
-	casted := page.(StackPage).Body
-
-	var res struct {
-		Stacks []ListedStack `mapstructure:"stacks"`
+func ExtractStacks(r pagination.Page) ([]ListedStack, error) {
+	var s struct {
+		ListedStacks []ListedStack `json:"stacks"`
 	}
-
-	err := mapstructure.Decode(casted, &res)
-	if err != nil {
-		return nil, err
-	}
-
-	var rawStacks []interface{}
-	switch casted.(type) {
-	case map[string]interface{}:
-		rawStacks = casted.(map[string]interface{})["stacks"].([]interface{})
-	case map[string][]interface{}:
-		rawStacks = casted.(map[string][]interface{})["stacks"]
-	default:
-		return res.Stacks, fmt.Errorf("Unknown type: %v", reflect.TypeOf(casted))
-	}
-
-	for i := range rawStacks {
-		thisStack := (rawStacks[i]).(map[string]interface{})
-
-		if t, ok := thisStack["creation_time"].(string); ok && t != "" {
-			creationTime, err := time.Parse(gophercloud.StackFmtTime, t)
-			if err != nil {
-				return res.Stacks, err
-			}
-			res.Stacks[i].CreationTime = creationTime
-		}
-
-		if t, ok := thisStack["updated_time"].(string); ok && t != "" {
-			updatedTime, err := time.Parse(gophercloud.StackFmtTime, t)
-			if err != nil {
-				return res.Stacks, err
-			}
-			res.Stacks[i].UpdatedTime = updatedTime
-		}
-	}
-
-	return res.Stacks, nil
+	err := (r.(StackPage)).ExtractInto(&s)
+	return s.ListedStacks, err
 }
 
 // RetrievedStack represents the object extracted from a Get operation.
 type RetrievedStack struct {
-	Capabilities        []interface{}            `mapstructure:"capabilities"`
-	CreationTime        time.Time                `mapstructure:"-"`
-	Description         string                   `mapstructure:"description"`
-	DisableRollback     bool                     `mapstructure:"disable_rollback"`
-	ID                  string                   `mapstructure:"id"`
-	Links               []gophercloud.Link       `mapstructure:"links"`
-	NotificationTopics  []interface{}            `mapstructure:"notification_topics"`
-	Outputs             []map[string]interface{} `mapstructure:"outputs"`
-	Parameters          map[string]string        `mapstructure:"parameters"`
-	Name                string                   `mapstructure:"stack_name"`
-	Status              string                   `mapstructure:"stack_status"`
-	StatusReason        string                   `mapstructure:"stack_status_reason"`
-	Tags                []string                 `mapstructure:"tags"`
-	TemplateDescription string                   `mapstructure:"template_description"`
-	Timeout             int                      `mapstructure:"timeout_mins"`
-	UpdatedTime         time.Time                `mapstructure:"-"`
+	Capabilities        []interface{}              `json:"capabilities"`
+	CreationTime        gophercloud.JSONRFC3339NoZ `json:"creation_time"`
+	Description         string                     `json:"description"`
+	DisableRollback     bool                       `json:"disable_rollback"`
+	ID                  string                     `json:"id"`
+	Links               []gophercloud.Link         `json:"links"`
+	NotificationTopics  []interface{}              `json:"notification_topics"`
+	Outputs             []map[string]interface{}   `json:"outputs"`
+	Parameters          map[string]string          `json:"parameters"`
+	Name                string                     `json:"stack_name"`
+	Status              string                     `json:"stack_status"`
+	StatusReason        string                     `json:"stack_status_reason"`
+	Tags                []string                   `json:"tags"`
+	TemplateDescription string                     `json:"template_description"`
+	Timeout             int                        `json:"timeout_mins"`
+	UpdatedTime         gophercloud.JSONRFC3339NoZ `json:"updated_time"`
 }
 
 // GetResult represents the result of a Get operation.
@@ -148,46 +96,11 @@
 // Extract returns a pointer to a RetrievedStack object and is called after a
 // Get operation.
 func (r GetResult) Extract() (*RetrievedStack, error) {
-	if r.Err != nil {
-		return nil, r.Err
+	var s struct {
+		Stack *RetrievedStack `json:"stack"`
 	}
-
-	var res struct {
-		Stack *RetrievedStack `mapstructure:"stack"`
-	}
-
-	config := &mapstructure.DecoderConfig{
-		Result:           &res,
-		WeaklyTypedInput: true,
-	}
-	decoder, err := mapstructure.NewDecoder(config)
-	if err != nil {
-		return nil, err
-	}
-
-	if err := decoder.Decode(r.Body); err != nil {
-		return nil, err
-	}
-
-	b := r.Body.(map[string]interface{})["stack"].(map[string]interface{})
-
-	if date, ok := b["creation_time"]; ok && date != nil {
-		t, err := time.Parse(gophercloud.StackFmtTime, date.(string))
-		if err != nil {
-			return nil, err
-		}
-		res.Stack.CreationTime = t
-	}
-
-	if date, ok := b["updated_time"]; ok && date != nil {
-		t, err := time.Parse(gophercloud.StackFmtTime, date.(string))
-		if err != nil {
-			return nil, err
-		}
-		res.Stack.UpdatedTime = t
-	}
-
-	return res.Stack, err
+	err := r.ExtractInto(&s)
+	return s.Stack, err
 }
 
 // UpdateResult represents the result of a Update operation.
@@ -202,19 +115,19 @@
 
 // PreviewedStack represents the result of a Preview operation.
 type PreviewedStack struct {
-	Capabilities        []interface{}      `mapstructure:"capabilities"`
-	CreationTime        time.Time          `mapstructure:"-"`
-	Description         string             `mapstructure:"description"`
-	DisableRollback     bool               `mapstructure:"disable_rollback"`
-	ID                  string             `mapstructure:"id"`
-	Links               []gophercloud.Link `mapstructure:"links"`
-	Name                string             `mapstructure:"stack_name"`
-	NotificationTopics  []interface{}      `mapstructure:"notification_topics"`
-	Parameters          map[string]string  `mapstructure:"parameters"`
-	Resources           []interface{}      `mapstructure:"resources"`
-	TemplateDescription string             `mapstructure:"template_description"`
-	Timeout             int                `mapstructure:"timeout_mins"`
-	UpdatedTime         time.Time          `mapstructure:"-"`
+	Capabilities        []interface{}              `json:"capabilities"`
+	CreationTime        gophercloud.JSONRFC3339NoZ `json:"creation_time"`
+	Description         string                     `json:"description"`
+	DisableRollback     bool                       `json:"disable_rollback"`
+	ID                  string                     `json:"id"`
+	Links               []gophercloud.Link         `json:"links"`
+	Name                string                     `json:"stack_name"`
+	NotificationTopics  []interface{}              `json:"notification_topics"`
+	Parameters          map[string]string          `json:"parameters"`
+	Resources           []interface{}              `json:"resources"`
+	TemplateDescription string                     `json:"template_description"`
+	Timeout             int                        `json:"timeout_mins"`
+	UpdatedTime         gophercloud.JSONRFC3339NoZ `json:"updated_time"`
 }
 
 // PreviewResult represents the result of a Preview operation.
@@ -225,60 +138,25 @@
 // Extract returns a pointer to a PreviewedStack object and is called after a
 // Preview operation.
 func (r PreviewResult) Extract() (*PreviewedStack, error) {
-	if r.Err != nil {
-		return nil, r.Err
+	var s struct {
+		PreviewedStack *PreviewedStack `json:"stack"`
 	}
-
-	var res struct {
-		Stack *PreviewedStack `mapstructure:"stack"`
-	}
-
-	config := &mapstructure.DecoderConfig{
-		Result:           &res,
-		WeaklyTypedInput: true,
-	}
-	decoder, err := mapstructure.NewDecoder(config)
-	if err != nil {
-		return nil, err
-	}
-
-	if err := decoder.Decode(r.Body); err != nil {
-		return nil, err
-	}
-
-	b := r.Body.(map[string]interface{})["stack"].(map[string]interface{})
-
-	if date, ok := b["creation_time"]; ok && date != nil {
-		t, err := time.Parse(gophercloud.StackFmtTime, date.(string))
-		if err != nil {
-			return nil, err
-		}
-		res.Stack.CreationTime = t
-	}
-
-	if date, ok := b["updated_time"]; ok && date != nil {
-		t, err := time.Parse(gophercloud.StackFmtTime, date.(string))
-		if err != nil {
-			return nil, err
-		}
-		res.Stack.UpdatedTime = t
-	}
-
-	return res.Stack, err
+	err := r.ExtractInto(&s)
+	return s.PreviewedStack, err
 }
 
 // AbandonedStack represents the result of an Abandon operation.
 type AbandonedStack struct {
-	Status             string                 `mapstructure:"status"`
-	Name               string                 `mapstructure:"name"`
-	Template           map[string]interface{} `mapstructure:"template"`
-	Action             string                 `mapstructure:"action"`
-	ID                 string                 `mapstructure:"id"`
-	Resources          map[string]interface{} `mapstructure:"resources"`
-	Files              map[string]string      `mapstructure:"files"`
-	StackUserProjectID string                 `mapstructure:"stack_user_project_id"`
-	ProjectID          string                 `mapstructure:"project_id"`
-	Environment        map[string]interface{} `mapstructure:"environment"`
+	Status             string                 `json:"status"`
+	Name               string                 `json:"name"`
+	Template           map[string]interface{} `json:"template"`
+	Action             string                 `json:"action"`
+	ID                 string                 `json:"id"`
+	Resources          map[string]interface{} `json:"resources"`
+	Files              map[string]string      `json:"files"`
+	StackUserProjectID string                 `json:"stack_user_project_id"`
+	ProjectID          string                 `json:"project_id"`
+	Environment        map[string]interface{} `json:"environment"`
 }
 
 // AbandonResult represents the result of an Abandon operation.
@@ -289,17 +167,9 @@
 // Extract returns a pointer to an AbandonedStack object and is called after an
 // Abandon operation.
 func (r AbandonResult) Extract() (*AbandonedStack, error) {
-	if r.Err != nil {
-		return nil, r.Err
-	}
-
-	var res AbandonedStack
-
-	if err := mapstructure.Decode(r.Body, &res); err != nil {
-		return nil, err
-	}
-
-	return &res, nil
+	var s *AbandonedStack
+	err := r.ExtractInto(&s)
+	return s, err
 }
 
 // String converts an AbandonResult to a string. This is useful to when passing
diff --git a/openstack/orchestration/v1/stacktemplates/results.go b/openstack/orchestration/v1/stacktemplates/results.go
index 7f4ea25..bca959b 100644
--- a/openstack/orchestration/v1/stacktemplates/results.go
+++ b/openstack/orchestration/v1/stacktemplates/results.go
@@ -2,7 +2,7 @@
 
 import (
 	"encoding/json"
-	"github.com/mitchellh/mapstructure"
+
 	"github.com/gophercloud/gophercloud"
 )
 
@@ -25,9 +25,9 @@
 
 // ValidatedTemplate represents the parsed object returned from a Validate request.
 type ValidatedTemplate struct {
-	Description     string                 `mapstructure:"Description"`
-	Parameters      map[string]interface{} `mapstructure:"Parameters"`
-	ParameterGroups map[string]interface{} `mapstructure:"ParameterGroups"`
+	Description     string                 `json:"Description"`
+	Parameters      map[string]interface{} `json:"Parameters"`
+	ParameterGroups map[string]interface{} `json:"ParameterGroups"`
 }
 
 // ValidateResult represents the result of a Validate operation.
@@ -38,14 +38,7 @@
 // Extract returns a pointer to a ValidatedTemplate object and is called after a
 // Validate operation.
 func (r ValidateResult) Extract() (*ValidatedTemplate, error) {
-	if r.Err != nil {
-		return nil, r.Err
-	}
-
-	var res ValidatedTemplate
-	if err := mapstructure.Decode(r.Body, &res); err != nil {
-		return nil, err
-	}
-
-	return &res, nil
+	var s *ValidatedTemplate
+	err := r.ExtractInto(&s)
+	return s, err
 }