Skip to content

Instantly share code, notes, and snippets.

@denis-ryzhkov
Last active February 24, 2021 04:34
Show Gist options
  • Save denis-ryzhkov/59efc5be73eebd099a66cd549226fba9 to your computer and use it in GitHub Desktop.
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`
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