7

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.

Yoh0xFF
  • 1,450
  • 2
  • 18
  • 31
  • Do you have problems with the Flask API or the conversion implementation? Can you also give some examples of correct conversions? – pastaleg Jun 09 '19 at 13:54

1 Answers1

8

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.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • 1
    There is now a recipe in the docs for automatically camel-casing keys: https://marshmallow.readthedocs.io/en/latest/examples.html#inflection-camel-casing-keys – Steve L Aug 13 '19 at 04:13