Last active
February 24, 2021 04:34
-
-
Save denis-ryzhkov/59efc5be73eebd099a66cd549226fba9 to your computer and use it in GitHub Desktop.
Ask `graphene_django` to convert `JSONField` to `GenericScalar` (JSON as is) instead of default `JSONString`
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from django.contrib.postgres.fields import JSONField | |
from graphene.types.generic import GenericScalar | |
from graphene.utils.str_converters import to_camel_case, to_snake_case | |
from graphene_django.converter import convert_django_field | |
def patch_graphene_django_JSONField_converter(auto_camel_case=True): | |
""" | |
Ask `graphene_django` to convert `JSONField` to `GenericScalar` (JSON as is) instead of default `JSONString` | |
Pros: | |
- Client does not need to make `JSON.parse()` | |
- A bit smaller data size (no need to escape each `"`), hence faster to transfer | |
Cons: | |
- Not found | |
@param auto_camel_case: bool - convert object keys to and from camelCase automatically, like `graphene` does | |
""" | |
@convert_django_field.register(JSONField) | |
def convert_JSONField_to_GenericScalar(field, registry=None): | |
Scalar = AutoCamelCasedScalar if auto_camel_case else GenericScalar | |
return Scalar(description=field.help_text, required=not field.null) | |
class AutoCamelCasedScalar(GenericScalar): | |
""" | |
JSON as is, but converting object keys to and from camelCase automatically | |
""" | |
@classmethod | |
def serialize(cls, value): | |
value = super().serialize(value) | |
return convert_keys(value, to_camel_case) | |
@classmethod | |
def parse_literal(cls, node): | |
value = super().parse_literal(node) | |
return convert_keys(value, to_snake_case) | |
@classmethod | |
def parse_value(cls, value): | |
value = super().parse_value(value) | |
return convert_keys(value, to_snake_case) | |
def convert_keys(data, to): | |
""" | |
Convert object keys either to camelCase or to snake_case | |
@param data: object - processed recursively | |
@param to: callable - applied to each key of each object found | |
""" | |
if isinstance(data, dict): | |
return {to(key): convert_keys(value, to) for key, value in data.items()} | |
if isinstance(data, (list, tuple)): | |
return [convert_keys(value, to) for value in data] | |
return data |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment