2

I am implementing a REST-like API and have just faced an interesting problem. There is a need to provide a resource with an open list of query parameters to filter the results. For example:

GET /api/items?field1=value1&field2=value2

Field names are configurable, so I don't have the complete list of possible names.

There are also parameters with special meaning, e.g. orderBy=field5

The problem is when there is a field with the same name as one of the pre-defined parameters. The API has to somehow distinguish between them.

Many command-line programs use two hyphens ("--") to mark the end of options and start of arguments. I think of something analogous in URLs.

Is there any good practice in this subject?

3
  • 2
    I use a ?filters=field:value approach. This way, I have a fixed set of Parameters and the 'configurable' stuff is hidden from the API
    – Pinoniq
    Commented Feb 13, 2015 at 9:48
  • @Pinoniq: I thought about an URL-encoded subquery, ie. ?filters=field1%3Dvalue1, but using another delimiter like ":" looks better.
    – pkalinow
    Commented Feb 13, 2015 at 12:12
  • Y, it makes for human&machine-readable format. field:value;otherfield:value just tells a nice story :)
    – Pinoniq
    Commented Feb 13, 2015 at 12:15

2 Answers 2

2

An easy solution is to add a prefix to all the query fields (or at least the customized). In my case the fields can be in different classes, e.g. "core" or "custom" so it is convenient to use prefixes to differentiate them. For example, "core.field1", "custom.field10". As a side effect, it will resolve the problem with conflicts. If someone adds a field called orderBy, it still will be able to be used for filtering without any conflict with the special parameter of the same name:

custom.orderBy=something&orderBy=field1
1

You can also mix the special fields with the field names. e.g.

/api/items?field1.orderByDesc=value1&field2=value2&field3.orderByAsc=value3

With this approach, you keep the field-specific filters close to the field without having to scan a separate parameter's value. Of course if you have some non-field related special params, such as pagination requests, then the "filters" special param is your best bet. You can make it less prone to conflicts by prefixing an improbable character sequence like

/api/items?field1.orderByDesc=value1&field2=value2&field3.orderByAsc=value3&z9x8y7rowStart=100&z9x8y7count=50

The z9x8y7 approach is similar to how PHP prefixes a $ before variable names.

On a different note, you may want to add a version number in the API itself, something like

/api/v1/items?........

This will allow you to keep multiple versions of your API alive, thus giving your consumers time to convert to a new version of your API when you release a new API. Some examples : http://www.lexicalscope.com/blog/2012/03/12/how-are-rest-apis-versioned/

2
  • I'm not sure if the url is the best place for the version number. A http header seems more RESTful. Commented Feb 18, 2015 at 7:48
  • Well, prefixing options with a strange value would make the queries less readable and hard to write manually... I would rather prefix the custom fields, making the name conflict impossible.
    – pkalinow
    Commented Feb 20, 2015 at 14:22

Your Answer

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

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