API design: query string nullable value
-
@cartman82 said in API design: query string nullable value:
fiddly coercion code
What? You literally just parse the parent ID as an integer and have the error case be "top level". There's less code here than there would be with a more restrictive API.
-
@Maciejasjmj said in API design: query string nullable value:
Not sure if I like the idea of query string parameters having different meaning when absent and empty. Might just be a personal peeve of mine, but I'd expect /endpoint?q= and /endpoint to have the same meaning. Kinda like having someFunction(x) and someFunction(x, null) do different stuff is a code smell to me.
Yeah.... ugh. Now I want to change it again...
-
@ben_lubar said in API design: query string nullable value:
What? You literally just parse the parent ID as an integer and have the error case be "top level". There's less code here than there would be with a more restrictive API.
Yeah in this specific case.
I was talking in general.
-
@cartman82 said in API design: query string nullable value:
But how do I then get just the node 17, without the entire subtree?
Do you really need me to tell you
/api/nodes/17/root
?
-
@RaceProUK said in API design: query string nullable value:
Do you really need me to tell you /api/nodes/17/root?
Ah
That's not very REST-ish.
/nodes/17
should be the node with id 17. That's it.Getting the entire subtree should be a special request, not the default behavior. I guess if you were explicitly making an API for a giant tree structure, it might make sense...
-
@Yamikuronue said in API design: query string nullable value:
@JazzyJosh if it's REST, it should be maybe a sub-node of the parent: so like:
/api/nodes for all nodes
/api/nodes/17/children for the children of node 17
but I'm not sure how to specify "only the top-level nodes" in this scheme eitherI refactored to this.
I now only havetop-level
switch to indicate "without parent", and that's it.Hope that will stop the waffling for a while...
-
@cartman82 said in API design: query string nullable value:
Hope that will stop the waffling for a while...
YMBNH
-
@cartman82 said in API design: query string nullable value:
That's not very REST-ish.
/nodes/17
should be the node with id 17. That's it.Depends whether you count the children of a node as part of the node or not, I guess.
-
@cartman82
/nodes/17/children
?
-
@cartman82 said in API design: query string nullable value:
That's not very REST-ish.
/nodes/17
should be the node with id 17. That's it.This bugs me every time I see it. Seems like that should be
/node/17
.
-
All this time, and no-one's yet posted
/node/js
.Until now
-
@boomzilla said in API design: query string nullable value:
@cartman82 said in API design: query string nullable value:
That's not very REST-ish.
/nodes/17
should be the node with id 17. That's it.This bugs me every time I see it. Seems like that should be
/node/17
.The collection endpoint should 100% be
/nodes
. Then you either have two endpoints to manage (because of things like/child/
vs/children
) or you deal with the weirdness of having a plural noun followed by a single ID for a singular response. Both have been done, but mostly I see people recommending the latter.
-
@Yamikuronue said in API design: query string nullable value:
Then you either have two endpoints to manage
Depending on how the routing is implemented, it should be possible to route both endpoints to the same action. I know you can do so in ASP.NET MVC with pattern-based routing (done this myself to catch outdated URLs and point them all to the same place). Not sure about attribute routing, but then there's nothing stopping you calling one action from the other. Done right, the extras maintenance demands on the code are minimal.
Still, I can't argue that fewer endpoints are easier to manage
-
@cartman82 Ok.
Then I'd have
/nodes/{id}
for a specific node/nodes/tree/
for the root/nodes/tree/{id}
for the tree for a specific id.
-
@Yamikuronue Or yeah, that. I think that makes more sense.
/nodes/{id}/tree
-
@cartman82 said in API design: query string nullable value:
@Dragnslcr said in API design: query string nullable value:
What is the range of values for parent_id? If it's a database sequence, a good value for nodes with no parent would be 0. If 0 is a valid node ID, you could use -1 instead. Not including for-parent as a query parameter would get you all nodes.
I considered that.
0
could work. But IMO it leaves equal or more space for client bug asnull
andfalse
, and isn't any cleaner or more "proper".It's cleaner and more proper because the only allowed values are nothing (for no filter) or an integer. Your parsing code becomes
if (query-parent-id exists) then parent-id = int(query-parent-id)
. You never have to deal with parsing string values - any non-integer value is an error.
-
@boomzilla said in API design: query string nullable value:
@cartman82 said in API design: query string nullable value:
That's not very REST-ish.
/nodes/17
should be the node with id 17. That's it.This bugs me every time I see it. Seems like that should be
/node/17
.Having both
/node/
and/nodes/
sounds like a recipe for disaster.@JazzyJosh said in API design: query string nullable value:
/nodes/{id}/tree
Suggests all descendants, not just children.
-
@PleegWat said in API design: query string nullable value:
Having both
/node/
and/nodes/
sounds like a recipe for disaster.No more (to me) than returning a node or multiple nodes from
/nodes/
. All of these have drawbacks, but the subtlety involved in getting one or many objects returned (and the fun that will ensue when you come across something that only has one child and makes you think it's broken) just sounds worse and worse to me.But I will admit to being a REST n00b. A lot of the principles that people have been talking about have just been going over my head, so for this subject you can probably think of me like one of @cartman82's interviewees.
-
@boomzilla said in API design: query string nullable value:
the subtlety involved in getting one or many objects returned
You don't, though. You always get a collection when you send a GET to
/nodes/
: give me the list of nodes. You always get a single object when you send a GET to/nodes/{id}
. Those are defined as separate routes. It's just the mental overhead of remembering to switch the plurality when changing your URL that is complicated about doing/node/{id}
instead.
-
@Yamikuronue You could implement
/nodes/{id}
to return a collection of one, though I've yet to see a REST API actually do this.
-
@RaceProUK yeah but why though?
The idea is that each endpoint defines a resource, using a Uniform Resource Locator. The endpoint at
/nodes
defines a single resource: the collection of all nodes. The endpoint at/nodes/{id}
defines a single resource: the node with id {id}.
-
@Yamikuronue said in API design: query string nullable value:
@RaceProUK yeah but why though?
It's basically strict typing for function return values -
/nodes
always returns a collection, regardless of how many elements are in it. It makes handling the return value on the client side simpler because you don't need to check if the return value is a scalar or a collection.
-
@Dragnslcr yeah, but
/nodes/{id}
isn't the same as/nodes
though./nodes
should 100% always return a collection, even if it's empty or has one element.
-
@Yamikuronue said in API design: query string nullable value:
@Dragnslcr yeah, but
/nodes/{id}
isn't the same as/nodes
though./nodes
should 100% always return a collection, even if it's empty or has one element.I do see them as the same function, just with different arguments. Of course, I've also always seen this
/foo/42/bar/Blah/
crap as a major case of complicator's gloves.
-
@Dragnslcr Whereas I'd see them as different routes with different methods behind them. So that's probably the difference.
-
@Yamikuronue said in API design: query string nullable value:
@RaceProUK yeah but why though?
It's a question of semantics: does it make more sense to return a singular node, or a collection of one?
-
@RaceProUK If you read
/18
as a filter to/nodes
then a collection. If you read it as its own endpoint, REST-style, then a single object.
-
@Yamikuronue said in API design: query string nullable value:
@RaceProUK If you read
/18
as a filter to/nodes
then a collection. If you read it as its own endpoint, REST-style, then a single object.Right....except a lot of the discussion here was filtering on the parent and returning the children. So it being a filter doesn't have to mean that it's a filter on the id, which is probably the issue.
It's this sort of maze of semantics that frustrates me and I do something like
/node/
and/nodes/
(or with the case of children maybe even something more distinct) to prevent confusion about this sort of thing or even debates in my head about which is better.Though I don't have a massive amount REST URLs to worry about so who really cares, I guess.
-
@boomzilla said in API design: query string nullable value:
This bugs me every time I see it. Seems like that should be /node/17.
But then you go to
/node
and get a whole bunch of nodes. Pick your poison.
-
@cartman82 said in API design: query string nullable value:
But then you go to
/node
and get a whole bunch of nodes.I wouldn't. I'd get nothing. Since I use java, that probably means I forget to check for null and my testers throw it back at me with NullPointerException stack traces in the ticket comments. But that's a personal problem.
-
@Yamikuronue said in API design: query string nullable value:
If you read
/18
as a filter to/nodes
then a collection.In proper REST style, the path part of the URL always names a thing (which might be a collection) and clients should not try to pick apart the meaning of parts of the URL. Filters are then applied to the thing to restrict the view that you are given (this will include things like paging for large collections) but would be described by query parameters, as you're still really talking about the same thing.
The server might pull parameters out of the path, but that's an implementation concept.
-
@dkf said in API design: query string nullable value:
In proper REST style, the path part of the URL always names a thing (which might be a collection) and clients should not try to pick apart the meaning of parts of the URL
Yes, that's what I was saying: if you read the URL in REST fashion, it is consistent.