Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python + Flask REST API, how to convert data keys between camelcase and snakecase?

I am learning Python, and coding simple REST API using Flask micro-framework.

I am using SQLAlchemy for Object-relational-mapping and Marshmallow for Object-serialization/deserialization.

I am using snakecase for my variable names(according to PEP8).

I need to convert JSON object keys from camelcase to snakecase when receiving data from front-end(Angular) and vice versa, when returning response data.

What is the best approach to do this using Flask ?

I was unable to find a good answer on the internet.

like image 870
Yoh0xFF Avatar asked Jun 09 '19 13:06

Yoh0xFF


1 Answers

You don't convert your keys, because you don't need to. Data is not code, the keys in JSON are not variables. They are not subject to PEP8 and you don't convert them.

If you have a convention for your JSON object keys, stick to it everywhere, in your front end and back end. Then use the Marshmallow 3.x data_key argument for a field to set the key name in the JSON document when loading and dumping.

E.g.

class UserSchema(Schema):
    first_name = fields.String(data_key="firstName")
    last_name = fields.Email(data_key='lastName')

If you want to automate this for all your fields, you could provide your own Schema.on_bind_field() implementation to generate a data_key value from the field name:

import re
from functools import partial

from marshmallow import Schema

_snake_case = re.compile(r"(?<=\w)_(\w)")
_to_camel_case = partial(_snake_case.sub, lambda m: m[1].upper())

class CamelCasedSchema(Schema):
    """Gives fields a camelCased data key"""
    def on_bind_field(self, field_name, field_obj, _cc=_to_camel_case):
        field_obj.data_key = _cc(field_name.lower())

Demo:

>>> from marshmallow import fields
>>> class UserSchema(CamelCasedSchema):
...     first_name = fields.String()
...     last_name = fields.String()
...
>>> schema = UserSchema()
>>> schema.load({"firstName": "Eric", "lastName": "Idle"})
{'first_name': 'Eric', 'last_name': 'Idle'}
>>> schema.dump({"first_name": "John", "last_name": "Cleese"})
{'firstName': 'John', 'lastName': 'Cleese'}

The examples section of the Marshmallow documentation has a similar recipe.

If you are using Marshmallow 2.x, then there are two arguments to set: load_from and dump_to.

like image 57
Martijn Pieters Avatar answered Sep 27 '22 21:09

Martijn Pieters