gojson-api

Go JSON:API (google/jsonapi) Pagination Example


Can someone show an example of how to output pagination links in the response using google/jsonapi? I've tried a couple approaches and none seems to work. I can directly output the object or an array of objects using MarshalPayload() and add links to the nodes by using the Linkable interface. I haven't yet seen an interface for the top level object so this is my current implementation.

        resp := map[string]interface{}{
            "data": users,
            "links": jsonapi.Links{
                "next": "next/2",
            },
        }

        c.Response().Header().Set(echo.HeaderContentType, jsonapi.MediaType)
        err = jsonapi.MarshalPayload(c.Response(), resp)
        if err != nil {
            return echo.ErrInternalServerError
        }

Which is complaining that: models should be a struct pointer or slice of struct pointers. The output I'm looking for is something similar to the one on the JSON:API Homepage. For example:

{
  "links": {
    "self": "http://example.com/articles",
    "next": "http://example.com/articles?page[offset]=2",
    "last": "http://example.com/articles?page[offset]=10"
  },
  "data": ...<snipped>
}

TIA


Solution

  • I think the issue is with your resp Map. That needs to be a struct. So you would need something like this:

    type Resp struct {
        Data []String `jsonapi:...`
        Links []Link `jsonapi:...`
    }
    
    resp := new (Resp)
    
    //here add your values to resp
    //like: resp.Data = users 
    
    c.Response().Header().Set(echo.HeaderContentType, jsonapi.MediaType)
    err = jsonapi.MarshalPayload(c.Response(), resp)
    if err != nil {
        return echo.ErrInternalServerError
    }
    

    UPDATE:

    Here's my sample code:

    type User struct {
        ID   int    `jsonapi:"primary,user"`
        Name string `jsonapi:"attr,name"`
    }
    
    type Articles struct {
        Users []*User `jsonapi:"relation,users"`
    }
    

    Handler function: (I didnt add any error handling, but you should)

    func (env *Env) TryJSONAPI(response http.ResponseWriter, request *http.Request) {
        resp := []*User{
            {ID: 3, Name: "username1"},
        }
        p, _ := jsonapi.Marshal(resp)
        payload, _ := p.(*jsonapi.ManyPayload)
        payload.Links = &jsonapi.Links{
            "self": fmt.Sprintf("https://example.com/articles"),
            "next": fmt.Sprintf("https://example.com/articles?page[offset]=%d", 2),
            "last": fmt.Sprintf("https://example.com/articles?page[offset]=%d", 10),
        }
        if err := json.NewEncoder(response).Encode(payload); err != nil {
            //handle error
        }
    }
    

    Output:

    {
      data: [
        {
          type: "user",
          id: "3",
          attributes: {
            name: "username1"
          }
        }
      ],
      links: {
        last: "https://example.com/articles?page[offset]=10",
        next: "https://example.com/articles?page[offset]=2",
        self: "https://example.com/articles"
      }
    }