I am implementing an API that returns how many users are using a particular app.
For example, say I want to return data that says
10 people are using only App1, 8 are using only App2, 8 are using only App3, and 15 are using both App1 and App2, and 20 are using all App1, App2, and App3.
How do we design the response structure in JSON?
I thought returning it in comma separated format
{
"App1": 10,
"App2": 8,
"App3": 8,
"App1,App2": 15,
"App1,App2,App3": 20
}
Is this format is right and semantically correct?
I thought of Array as well,
[
{"key": ["App1"], "count": 10},
{"key": ["App2"], "count": 8},
{"key": ["App3"], "count": 8},
{"key": ["App1", "App2"], "count": 15},
{"key": ["App1", "App2", "App3"], "count": 20}
]
but was doubtful on this on whether it is semantically correct.
Is there any better way? What is the best way to represent this data?
Think of this problem as three overlapping population in a Venn diagram. The best way to represent a Venn diagram is to represent each section as an ordered list of constituents and the number associated with it. This will uniquely represent each section to make a whole.
Now this goal is achieved by both the solutions. But the CSV as the keys of the JSON has a couple of flaws:
The Typescript definition will be difficult. In the first case, your Typescript definition would be a Record<string, number>
which is not as strongly typed (read less specificity) as the second one, which is
type App = 'App1' | 'App2' | 'App3';
type AppUsage = Array<{ key: Array<App>, count: number }>;
The first type is brittle. What if an app name has a comma? Your clients have to know the format. How would they differentiate between, say, "App1,App2"
vs "App1, App2"
(notice the space after the comma?). It is generally suggested to not use format dependent identifiers. Arrays are easier to work with and provide a better consistency.
If you use GraphQL, using plain JSON
, which is what the first approach is, is generally considered a bad practice.
So, the bottomline this should be the better way,
type App = 'App1' | 'App2' | 'App3';
type AppUsage = Array<{ key: Array<App>, count: number }>;
const appUsage: AppUsage = [
{"key": ["App1"], "count": 10},
{"key": ["App2"], "count": 8},
{"key": ["App3"], "count": 8},
{"key": ["App1", "App2"], "count": 15},
{"key": ["App1", "App2", "App3"], "count": 20}
]