RESTful API Expansion

Familiar with calling for a resource such as…

GET /foo/1

…and getting back some data like…

{
  uri: "/foo/1",
  name: "A Foo!",
  bars: [ "/bar/1", "/bar/2", "/bar/3", "/bar/4" ],
  baz: "/baz/23"
}

… only now to have to make four additional calls to figure out what in the world all this “bar” garbage is about?

Use Expansion in Your APIs

Take a lesson from many APIs out there, for example the JIRA API and Netflix API, and introduce an expand query parameter. Hydrate objects on-demand from the single call and lower your chatty web traffic. As a bonus, lowering this traffic overhead will certainly improve performance. No longer will your overly normalized API be the root cause for your speed issues. Sure, something else now is, but you can move on to tackle that one now.

From our example above…

GET /foo/1?expand=bars,baz

… to get back …

{
  uri: "/foo/1",
  name: "A Foo!",
  bars: [ "/bar/1", "/bar/2", "/bar/3", "/bar/4" ],
  baz: "/baz/23",
  expand: [
    {
      uri: "/baz/23",
      count: 4,
      label: "A friendly little baz."
    },
    {
      uri: "/bar/1",
      wassup: "I'm a bar!"
    },
    {
      uri: "/bar/2",
      wassup: "Another bar!"
    },
    {
      uri: "/bar/3",
      wassup: "All sorts of bar!"
    },
    {
      uri: "/bar/4",
      wassup: "Not to be overshadowed, I'm a bar as well!"
    }
  ]
}

… and now we have a bag appended to our object with the expanded resources.

Different Strokes for Different Folks

My personal preference is to implement it as above. For one, add as many resource expansions on the query param by commas, expand single references (baz) as much as arrays of references (bars). For second, all hydrated objects are added to a single bag called expand.

Other flavors include hydrating in-place. Instead of adding the bag, the object reference is replaced with the hydrated object itself. I’m not a fan of this one as the structure of the object changes – and must then be routed down a different logic path do be dealt with. With an expansion bag, the new data can be ignored without disrupting typical logic flow.

Yet another flavor involves an all-or-nothing and/or recursive expansion. All referenced objects are hydrated, either in-place or in the bag, digging into each object recursively until a given level is reached. The obvious risks here are space and time – time for the call to return given the object hydration that has to happen, space for the size of the returned call potentially returning your entire data store.

An important note: nobody can use expand as a property of any JSON object.

Written by mackay on July 18, 2013 Categories: API Tags: , , , , ,
Comments Off on RESTful API Expansion