Elegant Python function to convert CamelCase to snake_case?
Camel case to snake case
import re
name = 'CamelCaseName'
name = re.sub(r'(?<!^)(?=[A-Z])', '_', name).lower()
print(name) # camel_case_name
If you do this many times and the above is slow, compile the regex beforehand:
pattern = re.compile(r'(?<!^)(?=[A-Z])')
name = pattern.sub('_', name).lower()
To handle more advanced cases specially (this is not reversible anymore):
def camel_to_snake(name):
name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
return re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()
print(camel_to_snake('camel2_camel2_case')) # camel2_camel2_case
print(camel_to_snake('getHTTPResponseCode')) # get_http_response_code
print(camel_to_snake('HTTPResponseCodeXYZ')) # http_response_code_xyz
To add also cases with two underscores or more:
def to_snake_case(name):
name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
name = re.sub('__([A-Z])', r'_\1', name)
name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name)
return name.lower()
Snake case to pascal case
name = 'snake_case_name'
name = ''.join(word.title() for word in name.split('_'))
print(name) # SnakeCaseName
Convert camelCase to snakeCase
data = {
'firstName': 'abc',
'lastName': 'xyz',
'favoriteMovies': ['Star Wars', 'The lone ranger'],
'favoriteCountries': [
{'country': 'China', 'capitalCity': 'Beiging'},
{'country': 'India', 'capitalCity': 'New Delhi'}
]
}
new_data = {}
for key, value in data.items():
new_key_list = ['_' + x.lower() if x.isupper() else x for x in key]
new_key = ''.join(new_key_list)
if isinstance(value[0],dict):
new_value = []
for item in value:
temp_dict = {}
for key2, value2 in item.items():
new_key_list = ['_' + x.lower() if x.isupper() else x for x in key2]
new_key = ''.join(new_key_list)
temp_dict[new_key] = value2
new_value.append(temp_dict)
new_data[new_key] = new_value
else:
new_data[new_key] = value
Output:
{'first_name': 'abc', 'last_name': 'xyz', 'favorite_movies': ['Star Wars', 'The lone ranger'], 'capital_city': [{'country': 'China', 'capital_city': 'Beiging'}, {'country': 'India', 'capital_city': 'New Delhi'}]}
python function to convert camel case to snake case
To answer your second question first, this seems like a perfectly reasonable way to accomplish this task but it might not be as maintainable as other approaches since it can be kind of difficult to figure out how it works.
Here is a breakdown of what each line does:
string = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', string)
Adds an underscore immediately before every single uppercase character that is followed by one or more lowercase character, except at the beginning of the string.string = re.sub('(.)([0-9]+)', r'\1_\2', string)
Adds an underscore immediately before any group of consecutive digits, except at the beginning of the string.return re.sub('([a-z0-9])([A-Z])', r'\1_\2', string).lower()
Adds an underscore immediately before any uppercase character that has a lowercase character or digit before it, and converts the whole string to lowercase and returns.
How to convert snippet placeholder from CamelCase to snake_case
"camelToSnakeCase": {
"prefix": "test",
"body": [
"${1} -> ${1/([A-Z][a-z]+$)|([A-Z][a-z]+)/${1:/downcase}${2:/downcase}${2:+_}/g}"
],
"description": "transform from CamelCase to snake_case"
}
In order to differentiate between some last capture group like Abcd
and the preceding capture groups, I used an alternation:
([A-Z][a-z]+$)|([A-Z][a-z]+)
must be in this order
so group 1 will be at the end of the input because of the $
indicator and group 2 will not be at the end. And group 2s will always have at least one more group after them. Then, using the conditional ${2:+_}
only insert an underscore if there is a group 2 - because there must be a following group 1.
This keybinding version also works if you have a different workflow:
{
"key": "alt+3", // whatever keybinding you wish
"command": "extension.multiCommand.execute",
"args": {
"sequence": [
"cursorWordLeftSelect",
"editor.action.transformToSnakecase",
"editor.action.transformToLowercase",
// "cursorLineEnd" // if you want this
]
},
"when": "editorTextFocus && !editorHasSelection"
}
Type your word and trigger the keybinding. Uses the macro extension multi-command.
Python + Flask REST API, how to convert data keys between camelcase and snakecase?
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
.
Convert snake_case to camelCase in Python GraphQL resolver using Ariadne
Well, after reading this Ariadne discussion, I figured out that, I just had not to pass Ariadne snake_case_fallback_resolvers while creating Ariadne executable GraphQL schema.
So, basically, what I had done was -
from ariadne import load_schema_from_path, make_executable_schema, snake_case_fallback_resolvers, graphql_sync, ObjectType
type_defs = load_schema_from_path("./schema.graphql")
schema = make_executable_schema(type_defs, query, snake_case_fallback_resolvers)
What I did to fix this issue of not being able to map attributes in camelCase back to GraphQL response:
schema = make_executable_schema(type_defs, query)
# Just removed snake_case_fallback_resolvers from the function parameters
Also, I removed @snake_case_fallback_resolvers from the resolver function, to get attributes if any passed as input to the resolver in camelCase.
Related Topics
Round to 5 (Or Other Number) in Python
How to Flatten a Nested JSON Recursively, with Flatten_JSON
Difference Between Filter and Filter_By in SQLalchemy
Df.Append() Is Not Appending to the Dataframe
How to Decrypt Openssl Aes-Encrypted Files in Python
Class Method Decorator with Self Arguments
Roll Rows of a Matrix Independently
Error: " 'Dict' Object Has No Attribute 'Iteritems' "
Python Multithreading Wait Till All Threads Finished
Using Backslash in Python (Not to Escape)
How to Get Indices of a Sorted Array in Python
Seaborn Is Not Plotting Within Defined Subplots
How to Pass a Method as a Parameter in Python