How should HATEOAS Links in a json response be handled and why?

6,165 views
Skip to first unread message

Alexander Bätz

unread,
Oct 22, 2012, 4:46:10 PM10/22/12
to api-...@googlegroups.com

I'm in the process of designing a REST api and to be as RESTful as it gets i want to incorporate HATEOAS into the json responses.

Adding URLs to related resources is easy enough, but there was some discussion over the structure to use for those links.

A LOT of articles i found use a structure borrowed from ATOM feeds:

"links": [ 
   
{"rel": "self", "href":"http://example.org/entity/1"},
   
{"rel": "friends", "href":"http://example.org/entity/1/friends"}, ...
]

This raised some questions:

  • Is there a common json structure (beside adapting atom aggain) to describe references in resource properties? (for example the sender of a message).

The reference should probably be resolved as a url aggain, but would it be bad to include the simple id as well? kind of like:

"sender": { 
   
"id": 12345,
   
"href": "resource-uri"
}

My way of thought is that while HATEOAS makes it so a client doesn't need a lot of knowledge to use an api I'm kind of reluctant to remove the possibility to USE that knowledge (like accessing the profile picture by building the link client-side without looking up the user first). Another alternative would probably be to keep the "sender" as an id (or remove it entirely) and just add it as a Link.

Thanks in advance

Mike Kelly

unread,
Oct 22, 2012, 4:52:04 PM10/22/12
to api-...@googlegroups.com
Hey Alexander,

I agree with your reservations about using an array for links. fwiw,
there is a relatively well established media type that approaches
links in the way you are suggesting here, it's called hal+json. You
can read about it here:

blog post:
http://blog.stateless.co/post/13296666138/json-linking-with-hal

formal internet draft:
http://tools.ietf.org/html/draft-kelly-json-hal

I'm not sure I fully understood your final requirements, but perhaps
HAL's embedded resources may also be of use there?

Cheers,
Mike

Ian Joyce

unread,
Oct 22, 2012, 4:53:02 PM10/22/12
to api-...@googlegroups.com
A couple I'm aware of:
- JSON-LD -> http://json-ld.org/
- HAL -> http://stateless.co/hal_specification.html

--Ian
> --
> You received this message because you are subscribed to the Google Groups
> "API Craft" group.
> To unsubscribe from this group, send email to
> api-craft+...@googlegroups.com.
> Visit this group at http://groups.google.com/group/api-craft?hl=en.
>
>

Steve Klabnik

unread,
Oct 22, 2012, 6:40:49 PM10/22/12
to api-...@googlegroups.com
> Why use an array as a container? According to a java-script dev i know,
> access to the links would be easier with the links as properties of an
> object.

This sucks for multiple relations on one link.

Mike Kelly

unread,
Oct 22, 2012, 7:02:27 PM10/22/12
to api-...@googlegroups.com
Well, not exactly. For a start, single link relations per link is
in-line with the Web Linking RFC:

http://tools.ietf.org/html/rfc5988#section-3

In this specification, a link is a typed connection between two
resources that are identified by Internationalised Resource
Identifiers (IRIs) [RFC3987], and is comprised of:

* A context IRI,
* a link relation type (Section 4),
* a target IRI, and
* optionally, target attributes."

The Link header happens to use multiple space separated rels for
brevity but that actually represents multiple links that share the
same target IRI, each with a single rel.

From a design point of view, prematurely optimising away the common
case (single rel) in favour of multiple rel doesn't make a great deal
of sense when the former is supported naturally by JSON. I think most
API consumers would appreciate keeping this basic necessity (selecting
a link) as simple as possible.

At the end of the day, if you want "multiple rels" that are similar to
the Link header you can achieve the same effect simply by having
multiple links that all point at the same target, e.g. below I have
represented /bob's conflicting emotions toward /ted :

{
_links: {
self: { href: "/bob" },
hate: { href: "/ted" },
love: { href: "/ted" }
},
name: "bob",
description: "a confused little man",
age: 50
}

Steve Klabnik

unread,
Oct 22, 2012, 7:16:23 PM10/22/12
to api-...@googlegroups.com
Right, I'm primarily thinking about
http://www.w3.org/TR/html401/struct/links.html#adef-rel

> The value of this attribute is a space-separated list of link types.

I would agree that single-rel links are more common than multiple-rel
links, I'm just saying that that is one way in which that particular
notation is awkward.

Mike Schinkel

unread,
Oct 22, 2012, 7:40:53 PM10/22/12
to api-...@googlegroups.com

Steve can you elaborate on what you mean by "multiple relations", i.e. provide an example please?

BTW to all, I've been working on two (2) different generic API client projects recently (one for Node.js and one for WordPress/PHP) and they both attempt to treat "REST-like but not RESTful" APIs as if they were hypermedia-aware. IOW, the "hypermedia" links are defined in the client code as opposed to being transferred as part of an HTTP state transfer. 

While working on these I've struggled with modeling with links only. It seems that links as a building block from which "actions" that use problem-domain-specific verbs to define how to do something useful using a resource (i.e a link) and an HTTP verb.  The following is the pattern is what I'm seeing emerge with resources as fundamental and actions that combine a resource and an HTTP verb. The example below illustrates this by extending the conceptual example provided by the OP:


{
  "resources": { 
    "self":{
      "href":"http://example.org/",
      "methods":"GET"
    },
    "friends":{
       "href":"http://example.org/friends",
       "methods":"GET",
       "vars": {
           "friend_id": "$.[*].friend_id" // JSON Path
       }
    },
    "friend":{
       "methods":"GET,PUT,DELETE"
    },
    "new-friend":{
       "href":"http://example.org/friends/new",
       "methods":"POST"
    }    
  },
  "actions": {
    "add-friend":{
       "resource":"new-friend",
       "method":"POST"
    },
    "update-friend":{
       "resource":"friend",
       "method":"PUT"
    },
    "delete-friend":{
       "resource":"friend",
       "method":"DELETE"
    }
  }
}

The example above assumes there is no need to define the "get-self", "get-friends" and "get-friend" action because they are self-evident. 

Is anyone else seeing this pattern emerge?  Have you used it and/or decided to dismiss it?  Why or why not?  

Thanks in advance.

-Mike

Steve Klabnik

unread,
Oct 22, 2012, 8:34:34 PM10/22/12
to api-...@googlegroups.com
> Steve can you elaborate on what you mean by "multiple relations", i.e.
> provide an example please?

I have a paginated result set. They are indexed by zero. (duh ;) ). I
fetch page one. Now, page zero is described by both the 'first' and
the 'prev' relations.

<a href="..." rel="first prev">Page 0</a>

In the JSON representation, you'd have "first prev" for a key, which
makes it hard to find which link has the "first" relation.

Mike Schinkel

unread,
Oct 22, 2012, 9:12:34 PM10/22/12
to api-...@googlegroups.com
Thanks.  I believe Mike Kelly said something like this then:

}

Why does that not address the issue?

-Mike

Steve Klabnik

unread,
Oct 22, 2012, 9:38:20 PM10/22/12
to api-...@googlegroups.com
It could. Lots of repetition there.

Mike Schinkel

unread,
Oct 22, 2012, 10:52:32 PM10/22/12
to api-...@googlegroups.com
On Oct 22, 2012, at 9:38 PM, Steve Klabnik <st...@steveklabnik.com> wrote:
> It could. Lots of repetition there.

And that's the nature of hypermedia. Lots of duplicate links in many HTML pages.

-Mike

Steve Klabnik

unread,
Oct 23, 2012, 8:04:54 AM10/23/12
to api-...@googlegroups.com
Sure thing.

Seriously, guys, I'm not trying to fight about this, I'm just giving an example.

Peter Williams

unread,
Oct 23, 2012, 10:45:26 AM10/23/12
to api-...@googlegroups.com
Personally repeating urls for different rels doesn't bother me much.
Being able to have multiple links with the same rel is pretty
important, though. For example if you have a resource w/ json
representation and it also has a pdf and odt representations. We would
use two `alternate` links with different type parameters in the json
representation.

The list approach provides a obvious way do this but it is trickier
with a member based approach. I guess you could do

{_links: {
self: {href: "/..."}
alternate: [{href: "/...pdf", type: "app/pdf"}, {href:
"/...odt", type: "app/..."}]
}}

I don't really like that inconsistency, though. It doesn't look like
HAL supports this particular formulation. I wonder if it has some
other solution to this problem?

Peter

Mike Kelly

unread,
Oct 23, 2012, 12:44:00 PM10/23/12
to api-...@googlegroups.com
Hey Peter,

hal+json has always supported this:

http://tools.ietf.org/html/draft-kelly-json-hal-03#section-4.1.1

The reserved "_links" property is OPTIONAL.

It is an object whose property names are link relation types (as
defined by [RFC5988]) and values are either a Link Object or an array
of Link Objects.

Cheers,
M

Peter Williams

unread,
Oct 23, 2012, 4:26:06 PM10/23/12
to api-...@googlegroups.com
On Tue, Oct 23, 2012 at 10:44 AM, Mike Kelly <mikeke...@gmail.com> wrote:
> It is an object whose property names are link relation types (as
> defined by [RFC5988]) and values are either a Link Object or an array
> of Link Objects.

Hmm, i see that now. I must have skimmed right over it before.

Peter
barelyenough.org

Dave Gauer

unread,
Oct 23, 2012, 5:11:17 PM10/23/12
to api-...@googlegroups.com

Hi Alexander,



On Monday, October 22, 2012 1:46:10 PM UTC-7, Alexander Bätz wrote:

I'm in the process of designing a REST api and to be as RESTful as it gets i want to incorporate HATEOAS into the json responses.

Adding URLs to related resources is easy enough, but there was some discussion over the structure to use for those links.

A LOT of articles i found use a structure borrowed from ATOM feeds:

"links": [ 
   
{"rel": "self", "href":"http://example.org/entity/1"},
   
{"rel": "friends", "href":"http://example.org/entity/1/friends"}, ...
]



What you have here looks identical to what I chose for hm-json.


 

This raised some questions:

  • Is there a common json structure (beside adapting atom aggain) to describe references in resource properties? (for example the sender of a message).

I wanted to allow multiple links with the same "rel" property which this does not allow.   For example, a collection of items could link to each item and provide the same rel property for each:


        "links": [
            {
                "title": "Pride and Prejudice",
                "method": "OPTIONS",
                "href": "/books/57",
                "rel": "item",
                "description": "Go to Pride and Prejudice by Jane Austen"
            },
            {
                "title": "The Lord of the Rings",
                "method": "OPTIONS",
                "href": "/books/64",
                "rel": "item",
                "description": "Go to The Lord of the Rings by JRR Tolkien"
            },
            {
                "title": "Jane Eyre",
                "method": "OPTIONS",
                "href": "/books/71",
                "rel": "item",
                "description": "Go to Jane Eyre by Charlotte Bronte"
            }
]

Notice that all of these links have an "item" rel property.

This book list excerpt is from the hm-json Browser demo.  To see this example:
1. Head to https://bitbucket.org/ratfactor/hm-json-browser/
2. Click on the demo thumbnail
3. Click on the "Books" link in the hm-json Browser
4. Click on the "Get the book list" link


Mike Kelly's HAL method has the advantage that you can either enumerate through the links OR go to them directly by rel property (if you already know it).  Ultimately, I don't think there's a wrong way to do this as long as you're providing SOME sort of rel property.  The API clients will probably just be overjoyed to see that you have one at all!

-Dave

Mike Schinkel

unread,
Oct 23, 2012, 6:08:50 PM10/23/12
to api-...@googlegroups.com
Hi Dave,
On Oct 23, 2012, at 5:11 PM, Dave Gauer <ratf...@gmail.com> wrote:
I wanted to allow multiple links with the same "rel" property which this does not allow.   For example, a collection of items could link to each item and provide the same rel property for each:

        "links": [
            {
                "title": "Pride and Prejudice",
                "method": "OPTIONS",
                "href": "/books/57",
                "rel": "item",
                "description": "Go to Pride and Prejudice by Jane Austen"
            },
            {
                "title": "The Lord of the Rings",
                "method": "OPTIONS",
                "href": "/books/64",
                "rel": "item",
                "description": "Go to The Lord of the Rings by JRR Tolkien"
            },
            {
                "title": "Jane Eyre",
                "method": "OPTIONS",
                "href": "/books/71",
                "rel": "item",
                "description": "Go to Jane Eyre by Charlotte Bronte"
            }
]

Curious why this alternate wouldn't be a better solution?

"links": {
  "items": [
    {
      "title": "Pride and Prejudice",
      "method": "OPTIONS",
      "href": "/books/57",
      "description": "Go to Pride and Prejudice by Jane Austen"
    },
    {
      "title": "The Lord of the Rings",
      "method": "OPTIONS",
      "href": "/books/64",
      "description": "Go to The Lord of the Rings by JRR Tolkien"
    },
    {
      "title": "Jane Eyre",
      "method": "OPTIONS",
      "href": "/books/71",
      "description": "Go to Jane Eyre by Charlotte Bronte"
    }
  ],
  "another": "property"
}

-Mike

David Gauer

unread,
Oct 23, 2012, 6:59:09 PM10/23/12
to api-...@googlegroups.com
Hi Mike,
Perhaps it is! Obviously both contain the same information. If the
API's client was most interested in the rel property of the links,
then clearly your alternate is better. However, if the client were
interested in some other property (ordering them by method, or URI,
for example), then I think the flat list is preferable because it
doesn't require an additional inner loop to retrieve all of the links
and then collate them and search for the other desired property.

In other words, the flat list makes no assumptions about the
importance of any one property of the links. A series of arrays
nested inside an object's named property does.

In a specific scenario, I think one could think of *lots* of good
reasons to prefer your option. In a general case, I think I prefer
the flat array.

-Dave

mca

unread,
Oct 23, 2012, 7:14:30 PM10/23/12
to api-...@googlegroups.com
one of the reasons i like using arrays in JSON is that you get the ability to control the order of appearance when going through JSON parse/stringify.

Mike Schinkel

unread,
Oct 23, 2012, 7:20:46 PM10/23/12
to api-...@googlegroups.com
On Oct 23, 2012, at 6:59 PM, David Gauer <ratf...@gmail.com> wrote:
In other words, the flat list makes no assumptions about the
importance of any one property of the links.  A series of arrays
nested inside an object's named property does.

Good points.

In a specific scenario, I think one could think of *lots* of good
reasons to prefer your option.  In a general case, I think I prefer
the flat array.

I guess the ability to reference the rel as a property really resonated with me.  I do a lot PHP work and am always frustrated with a get an numerically indexed large array of objects vs. a ID-indexed large array of objects because I have to do the work to find the object rather than just let PHP(/Javascript) do it for me.  

FWIW.

-Mike

Dave Gauer

unread,
Oct 23, 2012, 7:34:03 PM10/23/12
to api-...@googlegroups.com
Yeah, I'm used to being the consumer of APIs too, not the author of them.  The server never gives you quite what you want - it's usually close at best.  I guess in an ideal world, the client would tell the server exactly how it wanted its data and the server would comply.  Hey, maybe I should create a PhD thesis around that concept and then send the development world on a wild-goose chase trying to put it into practice!  :-)

-Dave

Mike Schinkel

unread,
Oct 23, 2012, 8:01:40 PM10/23/12
to api-...@googlegroups.com
On Oct 23, 2012, at 7:34 PM, Dave Gauer <ratf...@gmail.com> wrote:
Yeah, I'm used to being the consumer of APIs too, not the author of them.  The server never gives you quite what you want - it's usually close at best. 

Yeah.  I often feel that API server developers and API client developers don't really want to concern themselves with the issues that the others face.  But I digress.

I guess in an ideal world, the client would tell the server exactly how it wanted its data and the server would comply. 

I've got an project I'm working on to address that but it's is too early for a public presentation on this list. OTH I'll tell you about it off-list if you are interested.

Hey, maybe I should create a PhD thesis around that concept and then send the development world on a wild-goose chase trying to put it into practice!  :-)

heh. You better be careful or you might look over your shoulder one day and find a mob of faithful with pitchforks and 
torches out for your blood...

-Mike

Mike Kelly

unread,
Oct 24, 2012, 3:33:29 AM10/24/12
to api-...@googlegroups.com


Sent from my iPhone

On 24 Oct 2012, at 00:14, mca <m...@amundsen.com> wrote:

> one of the reasons i like using arrays in JSON is that you get the ability to control the order of appearance when going through JSON parse/stringify.

Why do you want that ability? Do you have an example?

Cheers,
M

Mike Kelly

unread,
Oct 24, 2012, 3:52:17 AM10/24/12
to api-...@googlegroups.com
Hi David,

Link relations are the primary identifier of links, so they're a pivotal part of your hypermedia type's interface that need to be as accessible as possible. They're the only property that's required of a link other than the target URI. The vast majority, if not all, client interactions with an hypermedia API will be primarily driven by the link relations so I think it's reasonable to adopt that as the general case and to optimise for it.

Out of interest, did you have any specific use cases that you felt the array approach was better suited for?

Cheers,
M

mca

unread,
Oct 24, 2012, 9:49:52 AM10/24/12
to api-...@googlegroups.com
ensure the order of display of a set of links (i.e. a query set on a client)
ensure the order of processing of a set of links (i.e. client sends the server a set of links that should be "processed in the following order", etc.)
M

Mike Kelly

unread,
Oct 24, 2012, 10:26:07 AM10/24/12
to api-...@googlegroups.com
On Wed, Oct 24, 2012 at 2:49 PM, mca <m...@amundsen.com> wrote:
> ensure the order of display of a set of links (i.e. a query set on a client)

By display you mean display visually?

> ensure the order of processing of a set of links (i.e. client sends the
> server a set of links that should be "processed in the following order",
> etc.)

I'm trying to come up with an example use case in which I would need
this. Do you have one off the top of your head?


It is possible to achieve both of these via the hal+json approach,
right? If I understand correctly you are saying making these easier is
more important to you than easing basic link selection?

Cheers,
M

mca

unread,
Oct 24, 2012, 10:32:54 AM10/24/12
to api-...@googlegroups.com
yes, the first case is about visuals.
presenting a set of query options in a particular order to prompt the user to pick the "preferred" option first, etc.

and the second case is about processing.
i have a handful of cases where a client will submit a set of work (as links) in priority order.  

when the array is not available, one way i've solved this in hash tables is using an order element and scanning the list via the order element when building the display.


Cheers,
M

Mike Kelly

unread,
Oct 24, 2012, 10:39:28 AM10/24/12
to api-...@googlegroups.com
On Wed, Oct 24, 2012 at 3:32 PM, mca <m...@amundsen.com> wrote:
> yes, the first case is about visuals.
> presenting a set of query options in a particular order to prompt the user
> to pick the "preferred" option first, etc.
>
> and the second case is about processing.
> i have a handful of cases where a client will submit a set of work (as
> links) in priority order.
>

In both of those cases would each of the links share the same link relation?

mca

unread,
Oct 24, 2012, 10:42:18 AM10/24/12
to api-...@googlegroups.com

Mike Kelly

unread,
Oct 24, 2012, 10:44:36 AM10/24/12
to api-...@googlegroups.com
Sorry I meant within each case would the links share the same relation
--
Mike

http://twitter.com/mikekelly85
http://github.com/mikekelly
http://linkedin.com/in/mikekelly123

Mike Schinkel

unread,
Oct 24, 2012, 10:48:50 AM10/24/12
to api-...@googlegroups.com
On Oct 24, 2012, at 9:49 AM, mca <m...@amundsen.com> wrote:
> ensure the order of display of a set of links (i.e. a query set on a client)
> ensure the order of processing of a set of links (i.e. client sends the server a set of links that should be "processed in the following order", etc.)

I would question if both of those should be explicitly defined vs. implicitly defined? The former conflates data with presentation and JSON isn't a presentational format, and the latter requires precision in description so it would seem best to describe it in a manner that allowed multiple workflows and more flexibility than a serial list of tasks. JMTCW.

-Mike

mca

unread,
Oct 24, 2012, 10:49:12 AM10/24/12
to api-...@googlegroups.com
often yes, the list will be a list of at one of the same values (most all my designs use rel as a string of space-sep values).

Mike Kelly

unread,
Oct 24, 2012, 10:54:31 AM10/24/12
to api-...@googlegroups.com
On Wed, Oct 24, 2012 at 3:49 PM, mca <m...@amundsen.com> wrote:
> often yes, the list will be a list of at one of the same values (most all my
> designs use rel as a string of space-sep values).

ok so the would work for you?:

_links: {
self: { href: "foo" },
queries: [{
"href": "/foo?first-query"
},{
"href": "/foo?second-query
}]
}

mca

unread,
Oct 24, 2012, 10:57:43 AM10/24/12
to api-...@googlegroups.com
yes, in general that's the design i use for CJ.

mca
  }]
}

Dave Gauer

unread,
Oct 25, 2012, 1:03:19 AM10/25/12
to api-...@googlegroups.com
Hi Mike (Kelly),


Rel being required...what specification requires a rel property?  I didn't think REST or the concept of HATEOAS got that specific.

But I'm sure you're right that any sort of automated discovery of link relations would rely heavily on (or at least benefit greatly from) on a good rel naming scheme.

 

Out of interest, did you have any specific use cases that you felt the array approach was better suited for?


No, definitely not.  Either would work in practice.  I'm just trying to picture what I might want as a consumer of an API.  I think it's very difficult to predict how clients will use returned data.  An array seems to me to assume the least.

-Dave

Alexander Bätz

unread,
Oct 25, 2012, 2:35:17 AM10/25/12
to api-...@googlegroups.com
Atom does kind of. A link without a rel value has to be treated like the value is "alternate"

Mike Kelly

unread,
Oct 25, 2012, 6:21:44 AM10/25/12
to api-...@googlegroups.com
Hey Dave,

The spec I was referring to was the Web Linking RFC:

http://tools.ietf.org/html/rfc5988#section-3

In this specification, a link is a typed connection between two
resources that are identified by Internationalised Resource
Identifiers (IRIs) [RFC3987], and is comprised of:

- A context IRI,

- a link relation type (Section 4),

- a target IRI, and

- optionally, target attributes.


>>
>>
>> Out of interest, did you have any specific use cases that you felt the
>> array approach was better suited for?
>
>
>
> No, definitely not. Either would work in practice. I'm just trying to
> picture what I might want as a consumer of an API. I think it's very
> difficult to predict how clients will use returned data. An array seems to
> me to assume the least.

Well a link isn't just any old data and the rel isn't any old
property, right? Link relations are a required part of a link because
they are the primary means of identification, so given that I don't
think it's difficult or unreasonable to predict/assume that almost all
client usage of links will revolve around them. JSON gives us a
'native' way to model the relations and their links as key/value via
the JSON Object and makes the links easier to get to, so I think it
makes sense to play to JSON's strengths here.

In fact, I would go further an argue that constraining access to links
so that they have to be accessed via their relation (i.e. the hal+json
approach) is actually an important part of its design, because it
reduces the coupling surface of the media type, for example suppose a
representation had this set of links:

links: [{
"rel": "self",
"href": "/thing"
},{
"type": "application/user+json",
"rel": "owner",
"href": "/bar"
}]

this opens up the possibility of client code being written that
selects the owner link via the type attribute "application/user+json".
That's not good because it will break when further down the line the
representation changes to look like this:

links: [{
"rel": "self",
"href": "/thing"
},{
"type": "application/user+json",
"rel": "customer",
"href": "/baz"
},{
"type": "application/user+json",
"rel": "owner",
"href": "/bar"
}]

I agree with the principal that when designing a generic interface
that reducing assumptions is important, however in this case I think
that using link relations as the primary key to access links is a
reasonable assumption that significantly improves its usability and
robustness as an interface.

Cheers,
M

Dave Gauer

unread,
Oct 25, 2012, 1:48:28 PM10/25/12
to api-...@googlegroups.com
Hi Mike,


On Thursday, October 25, 2012 3:21:48 AM UTC-7, Mike Kelly wrote:
On Thu, Oct 25, 2012 at 6:03 AM, Dave Gauer <ratf...@gmail.com> wrote:
>
> Rel being required...what specification requires a rel property?  I didn't
> think REST or the concept of HATEOAS got that specific.
>
> But I'm sure you're right that any sort of automated discovery of link
> relations would rely heavily on (or at least benefit greatly from) on a good
> rel naming scheme.

Hey Dave,

The spec I was referring to was the Web Linking RFC:

http://tools.ietf.org/html/rfc5988#section-3



Ah, gotcha.  Thanks.

 
> No, definitely not.  Either would work in practice.  I'm just trying to
> picture what I might want as a consumer of an API.  I think it's very
> difficult to predict how clients will use returned data.  An array seems to
> me to assume the least.

Well a link isn't just any old data and the rel isn't any old
property, right? Link relations are a required part of a link because
they are the primary means of identification, so given that I don't
think it's difficult or unreasonable to predict/assume that almost all
client usage of links will revolve around them. JSON gives us a
'native' way to model the relations and their links as key/value via
the JSON Object and makes the links easier to get to, so I think it
makes sense to play to JSON's strengths here.



I don't really disagree with anything you're saying here except that it "makes the links easier to get to."  That's ONLY true if they are being used the way you or I would expect.

It's not a deal-breaker either way.  The data is there and it's easily parsed, and that's what matters.

 


Again, I definitely agree with you on principal.  Although if somebody's writing their application in a way that requires a single link with a specific 'type' attribute in order to work correctly, I think it's pretty safe to say that the whole REST/hypermedia thing is pretty much out the window anyway... :-)

My point is that in the HAL style there is less friction for finding a link by 'rel', but significantly more friction for finding a link by any other property.  And there MAY be perfectly valid reasons for finding (finding, mind you, not hard-coding) links or sorting by other properties.  I could dream some up, but they would be silly and contrived and would probably detract from my argument.

I must stress, though that I don't dislike the HAL style.  And I'm not married to the flat array.  I just think there's a valid argument for both.

-Dave

Jørn Wildt

unread,
Oct 26, 2012, 12:51:16 AM10/26/12
to api-...@googlegroups.com
I have been thinking a bit about this issue and come to the conclusion that the HAL approach where rels are indexed in a dictionary has some problems. Let me try to explain:

To lookup a rel-value, say "printable", a client programmer would do like this, since HAL is optimized for the simple/most-used use case:

  var url = data._links["printable"].href;

But what happens if the server decides to throw in multiple links for the same rel-value, for instance both PDF and Word representations of the printable stuff? Well, the above code breaks since data._links["printable"] would become an array instead of a single value.

Now a robust client has to write code like this:

  var url = null;
  if (data._links["printable"] IS ARRAY)
    then lookup in that array
  else
    select single value.

Unfortunately the dictionary approach encourages programmers to write the simple client code, assuming there will only be one link for each rel-value. This means encouraging programmers to write code that will break when the server decides to throw in multiple links for each rel-value.

A robust client would always have to write code that somehow respects that it may have to traverse an array to find the link it is looking for. So why not always use an array like this:

  _links : [
    { rel="printable", type="pdf", href="..." },
    { rel="printable", type="word", href="..." }
  ];

In that way we encourage (force) client programmers to write code that always iterates through the link array - instead of encouraging them to write brittle code that will break later on?

/Jørn

Mike Kelly

unread,
Oct 26, 2012, 2:15:29 AM10/26/12
to api-...@googlegroups.com


Sent from my iPhone
This isn't a big deal. You should obviously avoid churn by getting the plurality right first time (usually obvious). In cases where you don't, then just treat it like you would any other breaking change - by introducing an additional rel. i.e. either pluralize the rel or if you dont like plural rels change it some other way and keep it singular.

Cheers,
M


Jørn Wildt

unread,
Oct 26, 2012, 2:24:58 AM10/26/12
to api-...@googlegroups.com
Okay, got that. Thanks.

/Jørn

M


Mike Kelly

unread,
Oct 26, 2012, 3:56:13 AM10/26/12
to api-...@googlegroups.com
Just to add a couple more thoughts:

This is already an issue in plain, link-less JSON APIs - If you go
from a widget object to array of widget objects then clients are going
to break. I guess our familiarity with this challenge in JSON is
another reason why I don't consider it a big deal.

I do appreciate the concern, iirc the hal specification actually used
to have a note on it suggesting that singular links should only be
used when certain the plurality of the link will not change (e.g.
'self', 'canonical', 'mother', etc.), I can't remember why I edited it
out though. Maybe just to keep the word count down! :)

Jan Kronquist

unread,
Oct 30, 2012, 9:54:33 AM10/30/12
to api-...@googlegroups.com
I also like your proposal to use an attribute "name" to further differentiate links with the same rel, for example if there is another way than just the order of the links.


_links: { 
  self: { href: "foo" }, 
  queries: [{ 
    "href": "/foo?first-query", "name": "first" 
  },{ 
    "href": "/foo?second-query", "name": "second" 
  }] 
}

/Jan
Reply all
Reply to author
Forward
0 new messages