rest - relation context

情到浓时终转凉″ 提交于 2019-12-05 12:59:25

Another option is to embed the relationships right into the resources themselves. This makes it easier for a client to follow relationships between resources as they consume the service. For example, here's a hypothetical person with relationships to two organization resources via two membership resources, and one of those membership resources:

"person890": {
    "firstName": "Jane",
    "lastName": "Smith",
    "links": [{
        "rel": "membership",
        "href": "memberships/123"
    }, {
        "link": "membership",
        "href": "memberships/456"
    }]
}

"membership123": {
    "role": "chairwoman",
    "date: "12/23/2013",
    "term": "3 years",
    "links": [{
        "rel": "person",
        "href": "persons/890",
    }, {
        "rel": "organization",
        "href": "organizations/7575"
    }]
}

The basic principle at work here is HATEOAS - "Hypermedia as the Engine of Application State" - which enables a client with minimal understanding of your data to still interact with your API.

If your question is limited to the structure, I think there's no objectively correct answer. In principle, you should stick with whatever keeps consistency across your API. If there's nothing like this already implemented, I think it depends on what your goal is. If you want to keep the API as simple as possible, option 1 seems good enough.

Usually, I try to make the API as flexible as possible for the clients, so that they can get the exact information they need with as few requests as possible, and without bothering me to implement custom endpoints. Assuming organizations can be huge and have a lot of members, while a person can't be a member of a lot of organizations, this is what I'd do:

-I see no reason to have the two-level URI on both sides, so /persons/id can be the canonical URI for the person and /persons to the paginated collection of all persons across all organizations. organizations/id can be the URI for the organization, and /organizations/id/persons can give you a collection to all persons within an organization, and an alternative URI for the person.

  • I see no need for the 303, but that's a matter of option. You may have /organizations/id/persons/id redirect to /persons/id if you want.

  • Keep the /memberships/id as you described in 1.

  • Assuming you're using some form of HATEOAS, all resources should have links to the related resources.

A few other ideas I often implement that help usability and flexibility are:

  • All resources should have a self link to the canonical URI.

  • You should be able to query the collections. Like /memberships?person_id=X should generate a subset of the collection that lists all membership instances for that person.

  • You should be able to expand a resource representation to include an embedded representation. It may be something explicit, like /persons/id?expand=memberships should generate a representation of person with a field containing an embedded list of all memberships, or you can use something I call the zoom protocol. You have a parameter that indicates how many levels of relationships should be embedded, decreasing it as you progress through the relationships. So, /persons/id?zoom=1 will embed memberships, /persons/id?zoom=2 will embed memberships, and apply zoom=1 to the membership representations themselves, embedding organizations.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!