S
S
Sergey Savostin2016-03-04 11:37:19
API
Sergey Savostin, 2016-03-04 11:37:19

What should be the nesting of returned data in a RESTful API?

There is a standard data structure:

user_id
user_name
user_...

-----

group_id
group_user
group_name
group_...

-----

item_id
item_group
item_name
item_...

Let's say we call the GET items method (say top N by date). The result should be:
items : [
{id : 1, name : 'Name 1', group : 1},
{id : 2, name : 'Name 2', group : 1},
{id : 3, name : 'Name 3', group : 2},
{id : 4, name : 'Name 4', group : 3}
]
or
items : [
{id : 1, name : 'Name 1', group : 1, user: 1},
{id : 2, name : 'Name 2', group : 1, user: 1},
{id : 3, name : 'Name 3', group : 2, user: 1},
{id : 4, name : 'Name 4', group : 3, user: 2}
]
or
items : [
{id : 1, name : 'Name 1', group : {id : 1, name: 'Group 1', user: 1}},
{id : 2, name : 'Name 2', group : {id : 1, name: 'Group 1', user: 1}},
{id : 3, name : 'Name 3', group : {id : 2, name: 'Group 2', user: 1}},
{id : 4, name : 'Name 4', group : {id : 3, name: 'Group 3', user: 2}}
]
or
items : [
{id : 1, name : 'Name 1', group : {id : 1, name: 'Group 1', user: {id: 1, name: 'User 1'}}},
{id : 2, name : 'Name 2', group : {id : 1, name: 'Group 1', user: {id: 1, name: 'User 1'}}},
{id : 3, name : 'Name 3', group : {id : 2, name: 'Group 2', user: {id: 1, name: 'User 1'}}},
{id : 4, name : 'Name 4', group : {id : 3, name: 'Group 3', user: {id: 2, name: 'User 2'}}}
]
or
{ 
items : [
{id : 1, name : 'Name 1', group : 1},
{id : 2, name : 'Name 2', group : 1},
{id : 3, name : 'Name 3', group : 2},
{id : 4, name : 'Name 4', group : 3}
], 
groups : [
{id: 1, name: 'Group 1', user: 1},
{id: 2, name: 'Group 2', user: 1},
{id: 3, name: 'Group 3', user: 2}
], 
users : [
{id: 1, name: 'User 1'},
{id: 2, name: 'User 2'}
]
}

The first method is the most ascetic, universal, but in 99.9% of cases it will require the client to send a bunch more requests for normal display of information (get all groups and users by their id). Of the benefits - the simplicity of queries on the server side (all by PRIMARY KEY), no JOIN.
spoiler
However, in real life this is far from the case: for example, you need to exclude items of "banned" users -> JOIN on groups and users.

The penultimate method is the most complete, but the information is heavily duplicated. It is especially not clear what to include there if there are a large number of user_... and group_... fields. I saw that in some APIs you can specify what exactly to receive, but IMHO it is somehow inconvenient to specify a bunch of parameters in the request. And where to get their composition, do you need a diagram?
The last IMHO is the most optimal - the answer has everything you need to display exactly these items, the data is not duplicated (at least within this request). But let's say with pagination there will be questions: on the "second page" the already (possibly) received users and groups will return again, and perhaps some were not there. But still, there will be much less data and additional requests than in other options. And, to be honest, I have never seen such an approach anywhere. This is fine"
How generally "correctly" to return the connected data? How to understand what the API client will need?

Answer the question

In order to leave comments, you need to log in

3 answer(s)
S
Serge K, 2016-03-04
@korotkin

Everything, absolutely everything, for which there is an ID, should be loaded separately (a general request for metadata to the server during initialization, including the necessary ones in the object in the form of a generalized table ... a sea of ​​​​options). At the front, they will figure out how to put it together.
Otherwise, you will get a huge overhead for data adaptation and non-obvious data sets. Moreover, in the case of updating data in real time, you will have to dig up already received objects and recalculate something (as you're lucky here).

F
four4, 2016-03-04
@four4

You need to proceed from the fact that:
1. The programmer using your API should be as clear as possible. This is the main thing.
2. Speed ​​is important, but it's secondary to clarity.

M
Michael, 2018-08-31
@springimport

In short: common sense.
I would keep a balance. In places where additional data is clearly needed, you can enable them in advance. There is no single answer, unfortunately.
You will definitely like graphql. It is designed to solve problems like yours.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question