Added the ability to specify the JSON encoder
json.dumps() allows for a JSON encoder to be specified by the cls argument. This PR allows for a JSONEncoder to be passed through when constructing the GraphQLView object.
Supporting this PR allows for serialization of custom types which can be particular useful when defining custom graphene scalar types.
Coverage increased (+0.02%) to 96.512% when pulling 8077feedcfb6efd0c48b7f3e2f963bb281706aec on mleonard87:feature/specify-encoder into 282534584b2fea8e758eaee6c6e50e7f4b238669 on graphql-python:master.
Coverage increased (+0.04%) to 96.532% when pulling a3f84aab5774159a4372ff2fce284ce0e0666238 on mleonard87:feature/specify-encoder into 282534584b2fea8e758eaee6c6e50e7f4b238669 on graphql-python:master.
Coverage increased (+0.04%) to 96.532% when pulling a3f84aab5774159a4372ff2fce284ce0e0666238 on mleonard87:feature/specify-encoder into 282534584b2fea8e758eaee6c6e50e7f4b238669 on graphql-python:master.
Coverage increased (+0.04%) to 96.532% when pulling a3f84aab5774159a4372ff2fce284ce0e0666238 on mleonard87:feature/specify-encoder into 282534584b2fea8e758eaee6c6e50e7f4b238669 on graphql-python:master.
Coverage increased (+0.04%) to 96.532% when pulling a3f84aab5774159a4372ff2fce284ce0e0666238 on mleonard87:feature/specify-encoder into 282534584b2fea8e758eaee6c6e50e7f4b238669 on graphql-python:master.
@syrusakbary This PR looks good, is anything preventing it from merging?
Hi @erydo @mleonard87,
Thanks for taking time for making this PR. I think the serialization/deserialization is better to be assumed by the scalar type itself rather than the transport formatting language (json, msgpack, ...) so is universal and completely independent of it.
However I might be missing some of your context here. Would be great if you could provide an example of a Scalar type that could not be created without the "customize json serialization class" approach.
@syrusakbary I think you're mostly right, but a couple considerations:
- There are some better-performing serialization libraries that, if installed, are nice to use: http://artem.krylysov.com/blog/2015/09/29/benchmark-python-json-libraries/
- One of the use-cases that we'd run across was error serialization, for example; we have an internally-standard
JSONEncoderthat handles things likedatetimeand so on. Though I suppose that could be done in aformat_errorimplementation, it's harder to backport a custom encoder to instead produce a dict that would encode identically through a vanilla encoder.
Error serialization doesn't go through the Scalar system, though I think pretty much everything else does.
For error serialization, you can provide a custom error function format_error.
If you want to have another json serializer/deserializer (other than json, such as simplejson or ujson) I think that's will be a good idea to add into this repo.
But then the solution for that is not a custom decoder for json (as this PR is doing)
I have just stumbled upon this, I am having the same need.
We have a SQLAlchemy model that is using a custom class called 'MVStringBag', it's a bag of translateable strings with a default. It inherits from sa.STRING.
This custom type is used in several SQLAlchemy' Model Classes to provide 'automatic' multi-language strings in our API:
class OrderedPostPart(UnhideDeclBase):
(...redacted...)
# Groupname
groupname = Column(
MVStringBag.as_mutable(MVStringBagSAType), nullable=False
) # type: MVStringBag
(...redacted...)
It allows you to send a key to it, specifying the wanted language and, if that's not available, it'll return the default string.
class MVStringBagSAType(types.TypeDecorator):
impl = sqlalchemytypes.String
(...redacted...)
To generate the GraphQL Classes, I am using the Meta: feature you guys provide to automatically plug all of the Model classes' attributes to GraphQL Scalars and, since MVStringBag inherits from String, it'll be (correctly) a graphene.String (or a graphene.JSONString, in what i have seen in the wild) on the GraphQL side. which is the final type I expect to return to the API, so that translation is totally transparent and the api returns a simple and standard string.
But this class cannot be serialized because it's not one of the default types. So passing a custom JSONEncoder would be really useful.