LinkedPageBase follows a LinkPath element.
diff --git a/pagination/linked.go b/pagination/linked.go
index fc88a55..0376edb 100644
--- a/pagination/linked.go
+++ b/pagination/linked.go
@@ -1,29 +1,63 @@
package pagination
-import "github.com/mitchellh/mapstructure"
+import "fmt"
// LinkedPageBase may be embedded to implement a page that provides navigational "Next" and "Previous" links within its result.
-type LinkedPageBase LastHTTPResponse
+type LinkedPageBase struct {
+ LastHTTPResponse
+
+ // LinkPath lists the keys that should be traversed within a response to arrive at the "next" pointer.
+ // If any link along the path is missing, an empty URL will be returned.
+ // If any link results in an unexpected value type, an error will be returned.
+ // When left as "nil", []string{"links", "next"} will be used as a default.
+ LinkPath []string
+}
// NextPageURL extracts the pagination structure from a JSON response and returns the "next" link, if one is present.
// It assumes that the links are available in a "links" element of the top-level response object.
// If this is not the case, override NextPageURL on your result type.
func (current LinkedPageBase) NextPageURL() (string, error) {
- type response struct {
- Links struct {
- Next *string `mapstructure:"next,omitempty"`
- } `mapstructure:"links"`
+ var path []string
+ var key string
+
+ if current.LinkPath == nil {
+ path = []string{"links", "next"}
+ } else {
+ path = current.LinkPath
}
- var r response
- err := mapstructure.Decode(current.Body, &r)
- if err != nil {
- return "", err
+ submap, ok := current.Body.(map[string]interface{})
+ if !ok {
+ return "", fmt.Errorf("Expected an object, but was %#v", current.Body)
}
- if r.Links.Next == nil {
- return "", nil
- }
+ for {
+ key, path = path[0], path[1:len(path)]
- return *r.Links.Next, nil
+ value, ok := submap[key]
+ if !ok {
+ return "", nil
+ }
+
+ fmt.Printf("key = %#v, path = %#v, value = %#v\n", key, path, value)
+
+ if len(path) > 0 {
+ submap, ok = value.(map[string]interface{})
+ if !ok {
+ return "", fmt.Errorf("Expected an object, but was %#v", value)
+ }
+ } else {
+ if value == nil {
+ // Actual null element.
+ return "", nil
+ }
+
+ url, ok := value.(string)
+ if !ok {
+ return "", fmt.Errorf("Expected a string, but was %#v", value)
+ }
+
+ return url, nil
+ }
+ }
}