Supporting Kebab-Case Attributes And Query Params In Flask-Rest Jsonapi

Photo by Sam Loyd on Unsplash

Supporting Kebab-Case Attributes And Query Params In Flask-Rest Jsonapi

In the Open Event API Server Project, it was decided to dasherize all the attributes of the API.

What Was The Need For Dasherizing The Attributes In The API ?

All the attributes in our database models are seperated by underscores i.e first name would be stored as first_name. But most of the API client implementations support dasherized attributes by default. In order to attract third party client implementations in the future and making the API easy to setup for them was the primary reason behind this decision. Note: The dasherized version for first_name will be first-name. Also to quote the official json-api spec recommendation for the same:

Member names SHOULD contain only the characters “a-z” (U+0061 to U+007A), “0-9” (U+0030 to U+0039), and the hyphen minus (U+002D HYPHEN-MINUS, “-“) as separator between multiple words.

flask-rest-jsonapi is the API framework used by the project. We were able to dasherize the API responses and requests by adding inflect=dasherize to each API schema, where dasherize iss the following function:

def dasherize(text):
    return text.replace('_', '-')

flask-rest-jsonapi also provides powerful features like the following through query params:

But we observed that the query params were not being dasherized which rendered the above awesome features useless :( . The reason for this was that flask-rest-jsonapi took the query params as-is and search for them in the API schema. As Python variable names cannot contain a dash, naming the attributes with a dash in the internal API schema was out of the question.

For adding dasherizing support to the query params, change in the QueryStringManager located at querystring.py of the framework root are required. A config variable named DASHERIZE_API was added to turn this feature on and off.

Following Are The Changes Required For Dasherizing Query Params:

For Sparse Fieldsets in the fields function, replace the following line:

result[key] = [value]

with

if current_app.config['DASHERIZE_API'] is True:
    result[key] = [value.replace('-', '_')]
else:
    result[key] = [value]

For sorting, in the sorting function, replace the following line:

field = sort_field.replace('-', '')

with

if current_app.config['DASHERIZE_API'] is True:
    field = sort_field[0].replace('-', '') + sort_field[1:].replace('-', '_')
else:
    field = sort_field[0].replace('-', '') + sort_field[1:]

For Include related objects, in include function, replace the following line:

return include_param.split(',') if include_param else []

with

if include_param:
    param_results = []
    for param in include_param.split(','):
        if current_app.config['DASHERIZE_API'] is True:
            param = param.replace('-', '_')
        param_results.append(param)
    return param_results
return []