Hi all, I'm new to graphene by have used GraphQL in both go and node.js before and am finding the following difficult when moving across to Graphene.
I'd like to be able to call a REST API in the resolve function as per the example below. Note that the resolve_people method returns a dict.
class PersonType(graphene.ObjectType):
first_name = graphene.String(description='Persons first name')
last_name = graphene.String(description='Persons last name')
class Query(graphene.ObjectType):
people = graphene.List(PersonType)
def resolve_people(self, args, context, info):
resp = requests.get('http://acme.com/people/', headers={'Accept': 'application/json'})
return resp.json()
The rest endpoint http://acme.com/people/ returns JSON such as this:
[
{"first_name": "Bob", "last_name": "Jones"},
{"first_name": "John", "last_name": "Smith"}
]
If I execute the query I get back nulls for both first_name and last_name.
{
people {
first_name
last_name
}
}
In order for this to work I need to explicitly add resolve_first_name and resolve_last_name to my Person object. This seems like a lot of boilerplate code as JSOn documents with large numbers of fields are all going to require the same code like this:
class PersonType(graphene.ObjectType):
first_name = graphene.String(description='Persons first name')
last_name = graphene.String(description='Persons last name')
def resolve_first_name(self, args, context, info):
return self['first_name']
def resolve_last_name(self, args, context, info):
return self['last_name']
Is there a better way of doing this? I want to avoid the large amount of boiler plate and be able to use the dict as a starting point.
Any help here would be greatly appreciated.
hey @mleonard87 the reason this is happening is that ObjectTypes resolve object attributes, and what you have here is a dict with keys that are strings.
If from the request you can build a python object, you'll be in good shape.
Have a look here: http://stackoverflow.com/a/15882054 as to one method of doing so.
I have this problem at the moment锛孌o you have a good solution?
def _json_object_hook(d): return namedtuple('X', d.keys())(*d.values())
def json2obj(data): return json.loads(data, object_hook=_json_object_hook)
class Listing(ObjectType):
id = ID()
name = String()
class Review(ObjectType):
language = String()
listing = Field(Listing)
listing_id = ID()
class Query(ObjectType):
reviews = List(Review, id=Int(required=True))
def resolve_reviews(self, args, context, info):
api = get_reviews() # returns a Python dictionary
return json2obj(json.dumps(api.get_reviews(args.get("id"))["reviews"]))
Using the helper function from SO, we convert our dictionary to a json string and then to an object to that we can call methods on it. In this example, we also have some nested objects in the schema, and inner fields can be queried as well.
@nderkach, I have the below Rest response, How can I query for collectionId? Thank you in advance.
{
"count": "287",
"result": [
{
"case": {
"id": "167779"
},
"collectionAgentVersion": "",
"collectionDate": "2017-08-02 15:11:28.000",
"collectionFileType": "TSR",
"collectionId": "55CBD446E6F01ABFE05346CAA00A9B2E",
"customer": {
"companyName": ""
},
"device": {
"assetSerialNumber": "",
"clientId": "",
"deviceType": "",
"modelNumber": "",
"operatingSystem": "",
"serviceTag": "H6WC62S"
},
"importDate": "2017-08-02 20:11:28.0",
"projectId": "",
"totalCollections": ""
},
{
"case": {
"id": ""
},
"collectionAgentVersion": "",
"collectionDate": "2017-08-02 15:05:29.000",
"collectionFileType": "TSR",
"collectionId": "55CBC779F890B8ABE0534ACAA00AFF44",
"customer": {
"companyName": ""
},
"device": {
"assetSerialNumber": "",
"clientId": "",
"deviceType": "",
"modelNumber": "",
"operatingSystem": "",
"serviceTag": "1GR634J"
},
"importDate": "2017-08-02 20:05:29.0",
"projectId": "",
"totalCollections": ""
}
]
}
@m7albasha by analogy, you'd have a class like this:
class Result(ObjectType):
collectionId = ID()
then in your query something like this:
class Query(ObjectType):
results = List(Result)
def resolve_results(self, args, context, info):
responce = get_results() # get your json from the API here
return json2obj(json.dumps(responce)["result"])) # map to list of results
Hi @mleonard87 . We're currently going through old issues that appear to have gone stale (ie. not updated in about the last 6 months) to try and clean up the issue tracker. If this is still important to you please comment and we'll re-open this.
Thanks!
I've recently written an article on this topic, hope this helps.
@nderkach nice! I'll try and get it included in the documentation somewhere.
Most helpful comment
hey @mleonard87 the reason this is happening is that ObjectTypes resolve object attributes, and what you have here is a dict with keys that are strings.
If from the request you can build a python object, you'll be in good shape.
Have a look here: http://stackoverflow.com/a/15882054 as to one method of doing so.