api2go icon indicating copy to clipboard operation
api2go copied to clipboard

Why does MarshalToJSONWithURLs only add links for relationships?

Open grounded042 opened this issue 9 years ago • 17 comments

The JSON API format says that a top-level document may contain a links object. However, in api2go when you call MarshalToJSONWithURLs it only adds links to relationships. Could we get links for other objects as well?

grounded042 avatar Jul 16 '15 00:07 grounded042

Hi, a top level links object is currently used if you use our rest api and not the marshaller standalone. We have another ticket for links here #99

What other links apart from self do you have in mind? Or do you want a more generic feature which allows to add any link you like?

wwwdata avatar Jul 16 '15 05:07 wwwdata

I'm just using the standalone marshaller. What I was looking for was the self, and also the pagination links. I see that you have implemented them outside of the marshaller.

For now I'm making do by calling jsonapi.Marshal and then adding on a map[string]string to links off the object that is returned.

grounded042 avatar Jul 16 '15 22:07 grounded042

The reason for pagination to be implemented in the routing/api layer was that we wanted to make it as simple as possible.

I think for the standalone marshaller it would be the best if there is an interface for toplevel links too. So you just have to implement a method that returns a map[string]string. Or what do you think?

wwwdata avatar Jul 19 '15 15:07 wwwdata

Having to implement a method that returns a map[string]string sounds good. The only example In the JSON API format that would not work with that is

"links": {
  "related": {
    "href": "http://example.com/articles/1/comments",
    "meta": {
      "count": 10
    }
  }
}

But 1) I do not think that's a very common occurrence, and 2) I'm not sure if that's a top-level links object.

grounded042 avatar Jul 24 '15 17:07 grounded042

I am thinking about a good solution for this. It is very easy to achieve a toplevel links or toplevel meta object that is included in the marshaled result. For that you just call Marshal which gives you a map[string]interface{} and in that, you can set everything additional that you want.

So for the top level case, what would be best to have?

  • A Method that you can call that sets stuff into the map[string]interface[}?
  • An additional interface that the Marshal function would check for and if it finds it, also marshal meta or links top level objects?

And then there are relationships which can also have a meta object.

For example here:

// ...
{
    "type": "articles",
    "id": "1",
    "attributes": {
        "title": "Rails is Omakase"
    },
    "relationships": {
        "author": {
            "links": {
                "self": "/articles/1/relationships/author",
                "related": "/articles/1/author"
            },
            "meta": {
                "foo": "bar"
            },
            "data": {
                "type": "people",
                "id": "9"
            }
        }
    }
}
// ...

This is also allowed, see: http://jsonapi.org/format/#document-resource-object-relationships and we currently do not support it. I guess for this, a method (interface) that you have to implement would be best so the marshaler generated everything correctly.

wwwdata avatar Sep 27 '15 19:09 wwwdata

for the relationship stuff: we could put it into Reference https://github.com/manyminds/api2go/blob/master/jsonapi/marshal.go#L32

type Reference struct {
    Type        string
    Name        string
    Meta        map[string]interface{}
    IsNotLoaded bool
}

wwwdata avatar Sep 27 '15 20:09 wwwdata

I'm having the same issue as well. The concept of links is not limited by the spec to just "self", "related", and pagination, and it would be really useful to be able to include arbitrary domain-specific links, particularly on resources. The Twitch API for example has a number of arbitrary links fields.

derelk avatar Mar 22 '16 17:03 derelk

Sorry, just realizing I misunderstood the initial issue. I could file this as a separate request, but it broadly seems like links could be improved to be more flexible.

derelk avatar Mar 22 '16 17:03 derelk

hi! please open up another ticket, that would make things easier for us

sharpner avatar Mar 22 '16 20:03 sharpner

why another ticket i don't get it he means the same right? to just add meta stuff into relationships

wwwdata avatar Mar 22 '16 20:03 wwwdata

No, I'm talking specifically about allowing arbitrary keys and values in the links objects, which have nothing to do with relationships. The current implementation really only allows for links to contain self and related as far as I can tell, but the spec doesn't restrict links to these two concepts. I will open another ticket.

derelk avatar Mar 24 '16 22:03 derelk

You're talking about a meta field; I am talking about the links field.

derelk avatar Mar 24 '16 22:03 derelk

e.g. this should be possible

"author": {
    "links": {
        "self": "/articles/1/relationships/author",
        "related": "/articles/1/author",
        "arbitrarylink": "/some/other/resource",
    }
}

derelk avatar Mar 24 '16 22:03 derelk

ok :) can you help to work on this feature?

wwwdata avatar Mar 24 '16 22:03 wwwdata

Here's a PR with a possible solution: https://github.com/manyminds/api2go/pull/285

michaelkleinhenz avatar Jun 02 '17 21:06 michaelkleinhenz

so meta is implemented #291 but links is we still need to do @wwwdata right?

sharpner avatar Oct 26 '17 18:10 sharpner

yes

wwwdata avatar Oct 26 '17 19:10 wwwdata