How should I deal with object hierarchies in a RESTful API?

paulkmoore picture paulkmoore · Oct 5, 2010 · Viewed 28.9k times · Source

I am currently designing the API for an existing PHP application, and to this end am investigating REST as a sensible architectural approach.

I believe I have a reasonable grasp of the key concepts, but I'm struggling to find anybody that has tackled object hierarchies and REST.

Here's the problem...

In the [application] business object hierarchy we have:

Users 
 L which have one-to-many Channel objects
 L which have one-to-many Member objects

In the application itself we use a lazy load approach to populate the User object with arrays of these objects as required. I believe in OO terms this is object aggregation, but I have seen various naming inconsistencies and do not care to start a war about the precise naming convention .

For now, consider I have some loosely coupled objects that I may / may not populate depending on application need.

From a REST perspective, I am trying to ascertain what the approach should be. Here is my current thinking (considering GET only for the time being):

Option 1 - fully populate the objects:

GET api.example.com/user/{user_id}

Read the User object (resource) and return the User object with all possible Channel and Member objects pre-loaded and encoded (JSON or XML).

PROS: reduce number of objects, no traversal of object hierarchies required
CONS: objects must be fully populated (expensive)

Option 2 - populate the primary object and include links to the other object resources:

GET api.example.com/user/{user_id}

Read the User object (resource) and return the User object User data populated and two lists.

Each list references the appropriate (sub) resource i.e.

api.example.com/channel/{channel_id}
api.example.com/member/{member_id}

I think this is close to (or exactly) the implications of hypermedia - the client can get the other resources if it wants (as long as I tag them sensibly).

PROS: client can choose to load the subordinates or otherwise, better separation of the objects as REST resources
CONS: further trip required to get the secondary resources

Option 3 - enable recursive retrieves

GET api.example.com/user/{user_id}

Read the User object and include links to lists of the sub-objects i.e.

api.example.com/user/{user_id}/channels
api.example.com/user/{user_id}/members

the /channels call would return a list of channel resources in the form (as above):

api.example.com/channel/{channel_id}

PROS: primary resources expose where to go to get the subodinates but not what they are (more RESTful?), no requirement to get the subordinates up front, the subordinate list generators (/channels and /members) provide interfaces (method like) making the response more service like.
CONS: three calls now required to fully populate the object

Option 4 - (re)consider the object design for REST

I am re-using the [existing] application object hierarchy and trying to apply it to REST - or perhaps more directly, provide an API interface to it.

Perhaps the REST object hierarchy should be different, or perhaps the new RESTful thinking is exposing limitations of the existing object design.

Any thoughts on the above welcomed.

Many thanks

Paul

Answer

Pi Delport picture Pi Delport · Oct 5, 2010

There's no reason not to combine these.

  • api.example.com/user/{user_id} – return a user representation
  • api.example.com/channel/{channel_id} – return a channel representation
  • api.example.com/user/{user_id}/channels – return a list of channel representations
  • api.example.com/user/{user_id}/channel_list – return a list of channel ids (or links to their full representations, using the above links)

When in doubt, think about how you would display the data to a human user without "API" concerns: a user wants both index pages ({user_id}/channel_list) and full views ({user_id}/channels).

Once you have that, just support JSON instead of (or in addition to) HTML as the representation format, and you have REST.