GET /participants/1
200 OK
{
"_links": {
"self": { "href": "/participants/1" },
"next": { "href": "/participants/2" },
"novels": { "href": "/participants/1/novels" },
"profile": { "href": "/participants/1/profile" }
},
"name": "Dan",
"created_at": "2010-02-25T12:21:20",
"time_zone": { "region": "US/Pacific", "offset": "-07:00" },
"_embedded": {
"novels": [
{
"_links": {
"self": { "href": "/novels/123" },
"event": { "href": "/events/1" }
},
"title": "A Tailored Pursuit"
},
{
"_links": {
"self": { "href": "/novels/124" },
"event": { "href": "/events/2" }
},
"title": "Haphazard Names"
}
]
}
}
GET /participants/1
200 OK
{
"href": "/participants/1",
"name": "Dan",
"created_at": "2010-02-25T12:21:20",
"time_zone": { "region": "US/Pacific", "offset": "-07:00" },
"novels": [
{ "href": "/novels/123", "title": "A Tailored Pursuit" },
{ "href": "/novels/124", "title": "Haphazard Names" }
],
"profile": { "href": "/participants/1/profile" },
"next": { "href": "/participants/2" }
}
{
...
"profile": { "rel": "/relations/profile", "href": "/participants/1/profile" }
}
--
You received this message because you are subscribed to the Google Groups "API Craft" group.
To unsubscribe from this group and stop receiving emails from it, send an email to api-craft+...@googlegroups.com.
Visit this group at http://groups.google.com/group/api-craft?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
I like the compactness and the intuitive organization of this style of links. I think this is how most people approach links in json at least initially.
On May 22, 2013 4:36 PM, "Dan Duvall" <d...@mutual.io> wrote:
>
> {
> "href": "/participants/1",
This seems equivalent to the `self` rel. Is that the correct interpretation? If so why not use `self`?
> "novels": [
> { "href": "/novels/123", "title": "A Tailored Pursuit" },
Is this the title of the link or of the referenced novel? If is the former is there a way to expand links into an embedded representation of the referenced resource? If it is latter how do consumers distinguish between a link and and expanded references?
Peter
Barelyenough.org
HAL was created so that multiple variants (json and xml) could share the same abstract model (i.e. resource, links, embedded resources). So its possible to come up with another media type based on json that is more compact and is still HAL.
hal+json is designed the way it is mostly to keep the complexity of the spec down and to draw simple lines between what bits of the message are links, embedded resources, and properties. There's nothing to say that design is "right".. perhaps a more compact design might be more appealing?
If you want, you are more than welcome to bring this up on hal-discuss and see where that goes.
Good luck!
Cheers,
M
--
Most JSON-based hypermedia types (that are discussed in forums such as this, anyway) are aimed at being a "generic" media type in the sense that anyone can use the format for their specific purposes. I'm going to move forward assuming your proposal reflects this, as well.
1. With the "rel": [ { "href": "…" } } format, it's difficult to follow the Web Linking spec (RFC5988), which supports multiple relation values per link.
2. There are no controls for state transitions, so documentation would have to provide that to client developers. Some see this as a bonus for M2M, though I do not.
3. Name collisions. All responses need to be careful not to provide a property name that matches a link relation name.
With the format you outlined, in particular, I also see some parsing difficulties. How does a parser reliably pull media type semantics out of this response without first understanding some application semantics?
A parser would require some upfront knowledge/configuration to figure out what's a link and what's not. If the parsing rules are "any object in an array that contains an 'href' property is considered a link with the property name of its parent array being the link relation value," then so be it, but this could potentially bring some headaches.
def render_obj(name, obj) =
if (obj.href?) render_resource(name, obj) else render_property(name, obj)
def render_resource(name, obj) =
render_link(obj.href) { render_relation(obj.ref || [ name ], obj) }
def traverse(obj) =
for (value <- obj.properties)
if (value.href?) follow(value) else index(value)
def follow(obj) =
traverse(derefence(obj.href))
I encourage you to move forward with it. There's nothing wrong with listing constraints in your spec, either. Sometimes the limiting of a feature set actually becomes a feature in itself. :)
I'm also a little concerned about mixing data and metadata. IMO, an important goal is to make the API exchanges (particularly at development time) explain each other. That is, the data returned by, say, a read is a quick education on the data required in a create. In restructuring the links out to top level, you obscure this a bit. Does the presence of "href", "next", and "profile" in the reply to "GET /participants/1" mean I'm supposed to provide those values during a POST? I'm guessing probably not: those both sound generated rather than set. But other cases might be less obvious; the original's structure helps clarify.
Are you working in some context where compactness is so much more important than clarity?
On May 23, 2013 11:32 AM, "Repenning, Jack" <repenni...@gmail.com> wrote:
>
> On May 22, 2013, at 8:01 PM, Kevin Swiber <ksw...@gmail.com> wrote:
>
> > A parser would require some upfront knowledge/configuration
> to figure out what's a link and what's not.
How is knowing that objects which have an `href` member are links different from knowing that members of the `_links` object are links?
> I'm also a little concerned about mixing data and metadata.
How are you defining metadata? I don't think of the relationships between resources as meta. Ime, they are often the most important data.
> IMO, an important goal is to make the API exchanges (particularly at development
> time) explain each other. That is, the data returned by, say, a read is a quick education
> on the data required in a create. In restructuring the links out to top level, you
> obscure this a bit.
OTOH, if the reader is looking to understand both the structure and relationships pushing the links down a level may actually obscure things.
>Does the presence of "href", "next", and "profile" in the reply to "GET /participants/1"
> mean I'm supposed to provide those values during a POST? I'm guessing
> probably not: those both sound generated rather than set. But other cases might be
> less obvious; the original's structure helps clarify.
In some, hopefully increasingly number of, services links are part of the client specified data. For example, to transfer money between accounts the client might create a transfer resource specifying the source and destination accounts using links to them in the POST. In this situation not segregating links might be a bit less confusing. People generally don't seem to have serious issues figuring out which properties can and cannot be changed. Eg, if the response has a created at timestamp people don't get confused by the immutability of that property. I don't see why the fact that the data type of the property value is a link, rather than a string or number, would make that any more confusing.
Peter
Barelyenough.org
I wouldn't recommend designing a new hypermedia format, if there's some element of complexity which you believe is undesirable, I've found it's likely for good reason, including for consumers, if not producers.