Overview
Let's continue to build up the Listing
type.
In this lesson, we will:
- Add new fields to the schema
- Use the Connectors Debugger panel in the Explorer
- Learn how to map JSON responses to GraphQL schema fields
Adding new fields
The Airlock homepage displaying featured listings needs a little more than the id
and title
.
Let's add three more fields to the Listing
type for: the number of beds available (Int
), the cost per night (Float
) and whether or not the listing is currently closed for bookings (Boolean
).
Open up the
listings.graphql
schema file and find where theListing
type is defined.Add the three new fields along with descriptions.
listings.graphqltype Listing {id: ID!"The listing's title"title: String!"The number of beds available"numOfBeds: Int"The cost per night"costPerNight: Float"Indicates whether listing is closed for bookings (on hiatus)"closed: Boolean}When we save our changes,
rover dev
will restart automatically. Uh-oh, what errors do we see in the terminal?error[E029]: Encountered 3 build errors while trying to build a supergraph.Caused by:CONNECTORS_UNRESOLVED_FIELD: No connector resolves field `Listing.numOfBeds`. It must have a `@connect` directive or appear in `@connect(selection:)`.CONNECTORS_UNRESOLVED_FIELD: No connector resolves field `Listing.costPerNight`. It must have a `@connect` directive or appear in `@connect(selection:)`.CONNECTORS_UNRESOLVED_FIELD: No connector resolves field `Listing.closed`. It must have a `@connect` directive or appear in `@connect(selection:)`.
Let's fix those! The error gives a helpful hint: "It must have a @connect
directive or appear in @connect(selection:)
".
The router needs to know where these new fields are coming from. Do we need to make another network call to retrieve a listing's number of beds? Or is that data available in the response from the connector connected to the featuredListings
field? Let's have a look!
Adding to the selection
We can always check the JSON response for the /featured-listings
endpoint but for now let's go ahead and add those three fields to our selection.
Jumping back to the
listings.graphql
schema file, find theQuery.featuredListings
field.listings.graphqltype Query {"A curated array of listings to feature on the homepage"featuredListings: [Listing!]!@connect(source: "v1"http: { GET: "/featured-listings" }selection: """idtitle""")}In the
selection
, we'll add the three new fields:numOfBeds
,costPerNight
, andclosed
.listings.graphqlselection: """idtitlenumOfBedscostPerNightclosed"""
Checking our work
Let's save our changes and jump over to http://localhost:4000 where our local router is running.
We can add the new fields to our existing GetFeaturedListings
operation.
query GetFeaturedListings {featuredListings {idtitlenumOfBedscostPerNightclosed}}
And we get data back!
{"data": {"featuredListings": [{"id": "listing-1","title": "Cave campsite in snowy MoundiiX","costPerNight": 120,"numOfBeds": 2,"closed": null},{"id": "listing-2","title": "Cozy yurt in Mraza","costPerNight": 592,"numOfBeds": 1,"closed": null},{"id": "listing-3","title": "Repurposed mid century aircraft in Kessail","costPerNight": 313,"numOfBeds": 5,"closed": null}]}}
Looking more closely though, closed
seems to be returning null
for all the listings. null
is a perfectly valid value since the field is nullable... but let's dig into the errors!
Debugging mapping errors
To find out more about what's happening with each network call under the hood and debug any connector errors, we can use Explorer's Connectors Debugger.
Click on the arrow beside Response and select Connectors Debugger. (Note: Try refreshing the page if you don't see it!)
http://localhost:4000We can see that our network request call to
featured-listings
has one mapping error. Let's click on it to see more details.http://localhost:4000This opens the Mapping tab for the specific request we made, which shows more details like the error message:
"Property .closed not found in object"
.http://localhost:4000Let's click over to the Response body tab and examine the JSON response.
http://localhost:4000
Hmm, that's right, we can't find any JSON property called closed
! However, we do see closedForBookings
, which is the property we want.
Mapping JSON properties to GraphQL fields
When a JSON property doesn't quite match what we want to name it in our GraphQL schema, we'll need to take one extra step to map it.
The syntax looks like this:
selection: """fieldName: jsonName"""
The value we set as fieldName
is how we've defined the field in our schema. It's followed by a colon (:
) then the name of the corresponding field in the JSON response.
Jumping back to our schema file, we can update our selection with the
closed
field mapped to theclosedForBookings
property.listings.graphqlselection: """idtitlenumOfBedscostPerNightclosed: closedForBookings"""
Checking our work - part two!
Let's save our changes again and jump over to http://localhost:4000.
Re-run the GetFeaturedListings
operation...
query GetFeaturedListings {featuredListings {idtitlenumOfBedscostPerNightclosed}}
And we get some true
and false
values for closed
! 👏
{"data": {"featuredListings": [{"id": "listing-1","title": "Cave campsite in snowy MoundiiX","costPerNight": 120,"numOfBeds": 2,"closed": false},{"id": "listing-2","title": "Cozy yurt in Mraza","costPerNight": 592,"numOfBeds": 1,"closed": true},{"id": "listing-3","title": "Repurposed mid century aircraft in Kessail","costPerNight": 313,"numOfBeds": 5,"closed": false}]}}
Practice
selection
that is NOT defined in the schema? (For example, try adding latitude
to the selection
.)Key takeaways
- To troubleshoot why our GraphQL fields are not populating the right values from the REST API, we can use the Connectors Debugger. This tool lets us take a deeper look at each network call to see where any errors might have occurred.
- When there's a name mismatch between our GraphQL field name and JSON property, we can use the
selection
parameter to map them manually. To do this, we use the syntaxfieldName: jsonName
.
Up next
We've got featured listings running, now it's time to dig into a listing's details!
Share your questions and comments about this lesson
This course is currently in
You'll need a GitHub account to post below. Don't have one? Post in our Odyssey forum instead.