0

I am designing a REST service with multiple end points which will be servicing the following hierarchy:

Department has many Category Groups
Category Group has many Category(-ies)
Category has many Sub-Category(-ies)
Sub-Category has many Attributes.

Now, all these entities except for Attributes are optional meaning if I don't select anything on my hierarchical cascading dropdown based UI, I need to display the Attributes that belong to all Departments, if I only select a Department then I need to display Attributes that belong to all Category Groups belonging to that Department and so on.

The end goal is to save the hierarchy specifically the Attributes and their parental relationships.

I have this rough structure in my mind to populate the cascading dropdown on the UI:

GET /departments - gives a list of all departments.

GET /departments/[departmentIds]/categoryGroups - gives a list of category groups for all departments.

GET /departments/[departmentIds]/categoryGroups/[categoryGroupIds]/categories - gives a list of categories for the given category groups and departments.

And so on for sub-categories and attributes.

Can I shorten the last end point above to just be: GET /categoryGroups/[categoryGroupIds]/categories?

For all attributes in a department can I just have -GET /departments/[departmentIds]/attributes?

For all attributes in a category group - GET /categoryGroups/[categoryGroupIds]/attributes?

Will so many end-points be considered an end-point explosion of sorts? Are there any better ways of solving this?

Thanks.

3
  • How many rows total do you have? You could make a single endpoint that simply returns the entire tree, then you only need a single round trip to the server and handle the population of the dropdowns client side.
    – Rik D
    Aug 22, 2020 at 19:22
  • @RikD right now its not too bad but there is chance that it is extended at which point it will become messy.
    – linuxNoob
    Aug 22, 2020 at 19:26
  • YAGNI and KISS and you’ll probably be best of with a single endpoint for now.
    – Rik D
    Aug 22, 2020 at 19:30

2 Answers 2

1

In addition to @VoiceOfUnreason's answer (which I agree with).

Are there any better ways of solving this?

Matter of preferences. Honestly, to my experience, we strive to make our relational model extensible to our WEB interface for reasons that are not purely backed by meaningful requirements or needs.

To my experience, there's little value in structuring URIs reflecting complex hierarchies. The only reader for any WEB API is a web client and it can not care less about these hierarchies. They are meaningless 1.

This said.

Can I shorten the last endpoint above to just be: GET /categoryGroups/[categoryGroupIds]/categories?

Yes. Moreover. You can make it even shorter GET /categories?group=groupId.

As developer, If I ever request /categoryGroups, I will do it to work with categoryGroups, I wouldn't do it to search categories or any other related resource 2.

For all attributes in a department can I just have GET /departments/[departmentIds]/attributes?

Yes, if you want to force clients to be aware of the department before reaching its attributes. Or if you want to bind attributes' management to the department's management.

If attributes have a different life cycle, management, or maintenance than their respective parents or you just want to provide with such capability, then you could promote attributes offering a dedicated endpoint /attributes. Getting specific department's attributes would be as simple as GET /attributes?resource=department&resourceId=depId and same for categories. Or any other resource with attributes and all managed from a single endpoint.

No need to say that both approaches are not mutually exclusive. Usability or the way you want the API to be consumed is important. More than the URI structure.

I'm thinking in those API we define for specific Backoffice' features.


1: Ok, it provides guidance and a mental map for humans to understand how you have structured your data on the server-side, but we don't really need it. I, as an API consumer, don't care how you have organized your content, I only care how easy/hard is to consume it. Unlike machines, we (humans) value simplicity, more than complexity or sophistication.

2: If we were speaking about HATEOAS I could expect a link, pointing to categories. That's fine, but I still will expect to navigate to a different endpoint (resource).

4
  • Is it ok to use query strings? I thought I had read somewhere that using the whole path is more cleaner.
    – linuxNoob
    Aug 27, 2020 at 14:43
  • 1
    Sure It is. But still what drives the API design is its usability. The query string is a way to provide your endpoints with more capabilities (filtering basically). It's also (semantically) more appropiate for querying than the URI path.
    – Laiv
    Aug 27, 2020 at 14:50
  • For WEB APIs I find versatility a must have, since it helps to enhance the API with minor changes. If your API is meant to be public and consumed by 3th parties better make it resillient and versatile. If not, it's up to you. But I would make it the same way.
    – Laiv
    Aug 27, 2020 at 15:02
  • 1
    Anyways, for any experienced web developer, /categoríes?group=1 is way more cleaner than /categoryGroups/[categoryGroupIds]/categories. Overall if the intention is looking for categories within a specifc group.
    – Laiv
    Aug 27, 2020 at 15:08
1

REST doesn't care what spellings you use for your URI.

In particular, REST doesn't care whether or not the logical hierarchy of documents is expressed by the hierarchical parts of the identifiers.

In other words

/A
/A/B
/A/B/C
/A/B/C/D
/A/B/C/D/E

Is no better, and no worse, than

/A
/B
/C
/D
/E

As far as the machines are concerned, these are all just keys, used to identify documents in some logical document store. So long as none of the keys are ambiguous, it's all fine.

Because the machines don't care, we can design our identifiers so that they are easier for humans. There's no single convention for choosing identifiers, just like there's no single convention for choosing variable names; any spelling that is consistent with local convention is going to be fine.

1
  • 1
    @linuxnoob, do not conflate the relational database design with the object/class design. The class & UI design should be in "business domain" terms - the subject matter in the real world. There very well can be deep data relationships in DB tables but "out of sight and out of mind" as far as the user is concerned. Do not let a natural, high-level overlap end up as confusing, kludgy UI or potentially data-corrupting DB relations. Accept that you will be writing code to transliterate back and forth UI to DB.
    – radarbob
    Aug 23, 2020 at 15:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.