The humble
restaurant menu follows a common pattern where menu items are generally
separated into a logical hierarchy. At the top level, we may have breakfast
items, dinner items or drinks items. Each of these could be grouped further
into categories like meat dishes, fish dishes or pasta dishes (dinner items),
and again into burgers and steaks (meat dishes). Each item is then described so
that we (as humans) can make a choice on what to eat.

Now,
consider making that same menu available as an API (for machine consumption).
Think of the challenge that becomes immediately apparent; how do we describe
objects that contain similar properties? How should we model burgers for
example?

The natural
human tendency might be to describe each burger as an object with defined
properties. We may describe the “cheeseBurger”, the “baconBurger”, the
“hawaiianBurger” – this follows the menu approach (the intended business
purpose). Alternatively, we could define the “burgers” as an array and identify
each burger as an element with that array based on its property values.

There are a number of pros and cons to consider for each approach.

The “Named Object” approach

Pros

· The model is easy to understand (from a human perspective – developers are sometimes human)

· Consumers can navigate directly to the object needed; e.g. json.burgers.baconBurger

· Each object (burger) can evolve in isolation

· Each object can be managed via individual API end-points; e.g. http://api.sample.com/burgers/cheeseBurger

Cons

· Renaming or removing objects will lead to contract-breaking changes – forcing a new API version

· Filtering is usually done on attribute values. Doing so on objects is not intuitive.

· The object name provides identity within the interface schema. This name may need to be translated into an appropriate UI label and also makes localization challenging. The obvious solution would be to include a “label” attribute – but wouldn’t that be redundant?

The “Array” approach

Pros

· We can add, rename or remove objects (burgers) without effecting the interface model (no potential version changes).

· We can still retrieve a defined object via an API end-point; e.g. http://api.sample.com/burgers?type=Cheese%20Burger

Cons

· Consumers may need to loop through the array to find the required object by value.

· Objects have to maintain the same structure and cannot evolve in isolation.

The choice of which approach to take depends on the domain you are modeling. However, as the domain expert, the decision is yours – just understand the consequences of your choice.