Last week I posted a kind of vague question as I was trying to join data from an external Rest API with a local SQLAlchemy schema. Unsurprisingly, I didn't get a lot of responses and after some experimentation with parsing the response json into a temporary table I've decided to move away from this approach and add a new resolver for the external API that can be called separately from the resolver for SQLAlchemy. This is what I have so far for the querying the external API:
class Red(graphene.ObjectType):
redName = graphene.String()
accessLevel = graphene.String()
numBytes = graphene.Int()
class Query(graphene.ObjectType):
red = graphene.Field(Red, redName = graphene.String(required=True))
def resolve_red(self, info, **kwargs):
dataset_Red = <custom library for querying API>.dataset(kwargs['redName'])
dataset_Red.get()
resp = dataset_Red.properties
return json.dumps(resp)
GraphiQL recognizes my new resolver and will run the query with no errors but it returns no data. For example, if this is my query:
query{red(redName:"<dataset_name>") {
accessLevel
numBytes
}
}
I get the following response:
{
"data": {
"red": {
"accessLevel": null,
"numBytes": null
}
}
}
What did I miss? I'm thinking there's an issue with class definition. Can someone show me what I did wrong?
CodePudding user response:
I think you should return Red
type from resolver resolve_red
instead of json dumped string:
class Red(graphene.ObjectType):
redName = graphene.String()
accessLevel = graphene.String()
numBytes = graphene.Int()
class Query(graphene.ObjectType):
red = graphene.Field(Red, redName = graphene.String(required=True))
def resolve_red(self, info, **kwargs):
dataset_Red = <custom library for querying API>.dataset(kwargs['redName'])
dataset_Red.get()
resp = dataset_Red.properties
return Red(
redName=resp.get('redName'),
accessLevel=resp.get('accessLevel'),
NumBytes=resp.get('numBytes')
)
Or assuming fields in response are the same as Red
attributes:
class Red(graphene.ObjectType):
redName = graphene.String()
accessLevel = graphene.String()
numBytes = graphene.Int()
class Query(graphene.ObjectType):
red = graphene.Field(Red, redName = graphene.String(required=True))
def resolve_red(self, info, **kwargs):
dataset_Red = <custom library for querying API>.dataset(kwargs['redName'])
dataset_Red.get()
resp = dataset_Red.properties
return Red(**resp)
CodePudding user response:
Sound I found a solution that seems to work. The issue was the response type, I had to serialize and then deserialize it for flask (obvious right?).
I added this two functions:
def _json_object_hook(d):
return namedtuple('X', d.keys())(*d.values())
def json2obj(data):
return json.loads(data, object_hook=_json_object_hook)
And then changed my resolver to call json2obj
on the response:
def resolve_red(self, info, **kwargs):
dataset_Red = <custom library for querying API>.dataset(kwargs['redName'])
dataset_Red.get()
resp = dataset_Red.properties
return json2obj(json.dumps(resp))
I found this solution in another stackoverflow post but now I can't find the original. If anyone else finds it, please add a link in the comments and I'll add it to this answer.