Skip to content

Pagination access #64

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
gopherfortress opened this issue Jan 21, 2017 · 3 comments
Closed

Pagination access #64

gopherfortress opened this issue Jan 21, 2017 · 3 comments

Comments

@gopherfortress
Copy link

Great library thank you!

I wanted to ask, is there any way to access / unmarshal the pagination links that get sent by jsonapis like these:

"links": {
    "first": "http://somesite.com/movies?page[limit]=50&page[offset]=50",
    "prev": "http://somesite.com/movies?page[limit]=50&page[offset]=0",
    "next": "http://somesite.com/movies?page[limit]=50&page[offset]=100",
    "last": "http://somesite.com/movies?page[limit]=50&page[offset]=500"
 }

Ideally I'd like to provide access to these offsets in a separate struct as unmarshaling them into the Movie struct sounds strange! Thanks!

@aren55555
Copy link
Contributor

@gopherfortress we recently added features to easily add "links" when serializing/marshaling. Unfortunately the same cannot be said for deserializing/unmarshaling.

However there is still a way you can parse them out:

func TestManyPayload_withLinks(t *testing.T) {
	firstPageURL := "http://somesite.com/movies?page[limit]=50&page[offset]=50"
	prevPageURL := "http://somesite.com/movies?page[limit]=50&page[offset]=0"
	nextPageURL := "http://somesite.com/movies?page[limit]=50&page[offset]=100"
	lastPageURL := "http://somesite.com/movies?page[limit]=50&page[offset]=500"

	sample := map[string]interface{}{
		"data": []interface{}{
			map[string]interface{}{
				"type": "posts",
				"id":   "1",
				"attributes": map[string]interface{}{
					"body":  "First",
					"title": "Post",
				},
			},
			map[string]interface{}{
				"type": "posts",
				"id":   "2",
				"attributes": map[string]interface{}{
					"body":  "Second",
					"title": "Post",
				},
			},
		},
		"links": map[string]interface{}{
			KeyFirstPage:    firstPageURL,
			KeyPreviousPage: prevPageURL,
			KeyNextPage:     nextPageURL,
			KeyLastPage:     lastPageURL,
		},
	}

	data, err := json.Marshal(sample)
	if err != nil {
		t.Fatal(err)
	}
	in := bytes.NewReader(data)

	payload := new(ManyPayload)
	if err = json.NewDecoder(in).Decode(payload); err != nil {
		t.Fatal(err)
	}

	if payload.Links == nil {
		t.Fatal("Was expecting a non nil ptr Link field")
	}

	links := *payload.Links

	first, ok := links[KeyFirstPage]
	if !ok {
		t.Fatal("Was expecting a non nil ptr Link field")
	}
	if e, a := firstPageURL, first; e != a {
		t.Fatalf("Was expecting links.%s to have a value of %s, got %s", KeyFirstPage, e, a)
	}
}

@gopherfortress
Copy link
Author

Thanks for the answer!

Any idea of the amount of work that is being done when doing the

payload := new(ManyPayload)
if err = json.NewDecoder(in).Decode(payload); err != nil {
	t.Fatal(err)
}

My concern is that since links are at the very bottom of the document then it is possible that, assuming a big JSON document, twice the work will be done being done, once for decoding the pagination links and once for decoding the rest.

Unfortunately the same cannot be said for deserializing/unmarshaling.

Assuming there is indeed twice the work being done, any plans to support unmarshaling of pagination links?

Thank you!

@aren55555
Copy link
Contributor

@gopherfortress if all you are after is the "links" member there is definitely a more performant solution. The code sample I posted will traverse all of the "data" member which could be fairly lengthy. Take a look at our source code; I think you want to start by altering the OnePayload or ManyPayload to fit your use case of only parsing "links".

As for fully supporting unmarshalling "links" that is a goal - however initial investigation leads me to believe adding such a feature (in a simple way) would mean breaking the existing unmarshal method signatures. We still need to put more thought into this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants