Graphene: Raw JSON string as field value

Created on 19 Feb 2019  路  10Comments  路  Source: graphql-python/graphene

I have a large JSON string data field. I want to return this json string asis without first deserializing it to a python object, and serialize back when it gets sent out. What is the best way to do this?

I saw the JSONString type, but not sure if that is intended for this use. Note that I don't need type checking on this field. Just want to return the string as JSON data object without the overhead of deserialization and serialization.

question 馃摉 documentation

Most helpful comment

@ProjectCheshire kindly offered this example that allows one to override the serialization logic:

class JSONScalar(Scalar):
    """
    Arbitrary JSON Properties for features
    """

    @staticmethod
    def serialize(value):
        return value

    @staticmethod
    def parse_literal(node):
        return node.value

    @staticmethod
    def parse_value(value):
        return value

All 10 comments

@episodeyang could you not use the String type of this? And then do the deserialization in the client?

Hey @jkimbo! Thanks for your reply!

I consider this to be a problem on the serving-side, as an implementation detail behind the graphQL schema.

Suppose I have a large JSON string (5MB) that is read from postgreSQL. Deserializing it into python object, then serialize back is unnecessary. Would be nice if we could __insertUnsafeJson__ into the final graphQL response.

@episodeyang the GraphQL spec does not allow returning unstructured data. The only scalar types it allows are Int, Float, String, Boolean, ID (special kind of a String) and derivative of those (meaning that you can implement custom serialize\deserialize logic but what goes on the wire is of one of the mentioned types).
So an __insertUnsafeJson__ would not be "the GraphQL way".

However, if you just send your JSON structure as a String (and not JSONString) you will not go through the deserializing into python object just to serialize back.

@ekampf This is below the layer of abstraction of GraphQL. This has nothing to do with the scalar types in GraphQL.

Let me explain this with better clarity:

Suppose you want to return a result in the form of

result {
   name: "Ge Yang"
   details:   { ... some large blob of object, 10 mb insize with nested children }
}

When we return the graphene raw result, it needs to be serialized to be sent out as a json string. Note that the data that is being transmitted has to be a string.

What I am suggesting, which wasn't really clear in the original post, is that we should offer a way to by-pass the json-string to python object, then to json-string again loop. This has nothing to do with grahpQL types. This is a directive/short-cut for avoiding a slow and unnecessary python deserialization step.

This optimization is quite necessary for some of the large blobs that are read from a database.

In this context, the consumer of this particular query still gets a normal json object for the field details. However, we avoid the json-string to python object, then back to json-string loop.

@ekampf The critical point is that for the consumer, this particular field is resolved as a generic object type. Not a JSONString, or a String.

class Query(ObjectType):
  details = String()

  def resolve_details(root, info):
    details: str = fetch_big_json_string_from_postgress()
    return details

At which point is your big postgress blob deserialized into and python object and then back to to string in this case?

@ProjectCheshire kindly offered this example that allows one to override the serialization logic:

class JSONScalar(Scalar):
    """
    Arbitrary JSON Properties for features
    """

    @staticmethod
    def serialize(value):
        return value

    @staticmethod
    def parse_literal(node):
        return node.value

    @staticmethod
    def parse_value(value):
        return value

Not sure how this is different from Generic. And the string passed like this is served as string, not as part of the whole JSON sctructure.

Was this page helpful?
0 / 5 - 0 ratings