How to return json in python graphene resolver without backslashes before quotation marks How to return json in python graphene resolver without backslashes before quotation marks json json

How to return json in python graphene resolver without backslashes before quotation marks


Your initial result of

{  "data": {    "questionnaire": "{\"s1\": \"Section 1\", \"s2\": \"Section 2\", \"s3\": \"Section 3\", \"s4\": \"Section 4\"}"  }}

is the intended behavior. After all, questionnaire resolves to a JSONString. Since it is a string it must be double quoted, thus its inner quotations must be escaped. This is according to JSON's standards.

To use that string you, would have to run some sort of JSON parser on the data.questionnaire object. In javascript, for instance, it would be something like:

var data;// Fetching logic to get the data object from your GraphQL servervar sections = JSON.parse(data.questionaire);// Now you can access its objectsconsole.log(sections.s1) // Should print "Section 1" on the dev console

However, the method described above is not ideal if the keys of sections are not predetermined (sections.s5 may be defined in one case but undefined in another). Instead, you might rather have an array that you can iterate over. To do this, you would have to define a "model" that has explicit key-value pairs. Doing this way is format suited for GraphQL, too. For instance:

import graphene# Our new modelclass Section(graphene.ObjectType):    key = graphene.String()        # dictionary key    header = graphene.String()     # dictionary value# Your previous schema with modificationsclass Query(graphene.ObjectType):    # questionnaire = graphene.types.json.JSONString(description='JSON result test')    # Return a list of section objects    questionnaire = graphene.List(Section)    def resolve_questionnaire(self, info: graphql.ResolveInfo):        sections = {          's1': "Section 1",          's2': "Section 2",          's3': "Section 3",          's4': "Section 4"        }        sections_as_obj_list = [] # Used to return a list of Section types        # Create a new Section object for each item and append it to list        for key, value in sections.items(): # Use sections.iteritems() in Python2            section = Section(key, value) # Creates a section object where key=key and header=value            sections_as_obj_list.append(section)        # return sections        return sections_as_obj_list

Now, if we run the query:

query {  questionnaire {    key    header  }}

It returns a JSON array that can be iterated through.

{  "data" {    "questionnaire": [      {        "key": "s1",        "header": "Section 1"      },      {        "key": "s2",        "header": "Section 2"      },      {        "key": "s3",        "header": "Section 3"      },      {        "key": "s4",        "header": "Section 4"      },    ]  }}


Graphene now has a GenericScalar type for this.

from graphene.types import generic...errors = generic.GenericScalar()


You can just subclass the JSON type and replace the serialize method:

class Any(JSON):    @staticmethod    def serialize(dt):        return dt

Then instead of

questionnaire = Field(JSON)

write

questionnaire = Field(Any)

Yes, this does break the strictly-typed spirit of GraphQL, but if that's what you want to do, there's how to do it. Note that this is an output-only hack — it won't allow you to accept arbitrary structures as arguments.