Overview
Let's explore how to work with enum types in our mapping.
In this lesson, we will:
- Learn how to match and replace values
- Learn about the
@
symbol
Matching values
Let's return to our schema. We've given our Product
type a new field: category
, which returns an enum of type Category
.
type Product {# ... other product fields"The category this product belongs to"category: Category!}
We're using an enum type for the category
field so that we can group our products into a set of standard, predefined categories. This lets us limit categories to just the options that we specify: ACCESSORIES
, APPAREL
, and MISC
, among others.
enum Category {ACCESSORIESAPPARELDECORELECTRONICSGAMESMISC}
Back in our JSON, we'll see our products include their own "category"
field; its value can range from "toys", to "home decor", to many more. Adding more diverse products to our inventory will presumably result in lots more categories we can't begin to predict.
Already we can see that the values in our data don't exactly align with the options in our Category
enum. So in order to sync our JSON response with our schema definition, we can put the match
method to work.
With match
, we define what some resulting value should be based on its original value. In practice, this means defining various cases that our mapping will attempt to "match" each value against; if the value matches, the method swaps in the value that we specify instead.
This means we can transform what we return for a product's category ("gear") into the corresponding value we want (ACCESSORIES
). We can also define a catch-all case, in the event that none of our options are matched (such as MISC
for "Miscellaneous" in our enum
type).
Let's return to the mapping playground. A product's category
appears outside of its variants
array, so let's add our new property at the same level of indentation as our id
, name
, tagline
, and tags
fields.
$.products {idnametagline: descriptiontags {id: tagIdname}categoryvariants->first {price: price.originalquantity: inventory.quantityspecifications: specifications->entries {name: keyvalue}}}
The category
property is what we're going to apply our match
transform to, but it's also the name we want to use as our output key. So right away let's add a colon (:
) followed by category
again.
category: category
Nothing's changed—yet. Now let's apply the match
method. Add the arrow (->
) followed by match
and a set of parentheses (()
).
category: category->match()
A red squiggly will alert us to what's missing from match
:
Method ->match did not match any [candidate, value] pair.
Let's see how this works by specifying what we want the category from our first product, "gear"
, to be converted to. In this case, let's choose the ACCESSORIES
option from our Category
enum.
We'll pass a set of square brackets ([]
) into match()
. Here we need to provide a pair of values: first, the value that should be matched, then what the matching value should be converted to.
category: category->match(["gear", "ACCESSORIES"])
Right now, our mapping syntax will still show an error: this is because some categories in our data were not "matched" and replaced with a different value. To fix this, let's keep going.
Further down in our products data, we'll find a category of "clothing"
. Let's add another condition to our match
method to return "clothing"
as APPAREL
. Each new "candidate/value" pair should be contained within its own set of square brackets, with each pair separated by a comma.
category: category->match(["gear", "ACCESSORIES"],["clothing", "APPAREL"])
We could keep going this way—but as our list of products grows, we might encounter more and more new categories we'd then have to account for in the match
method.
Ideally, we'd bucket any new categories we haven't already accounted for into the MISC
option in our enum, for "Miscellaneous". So how do we pass a catch-all value in case there aren't any other matches for a particular category? Introducing: the @
symbol!
The @
symbol
Whenever we apply a transform method to a value, we can refer to the value being transformed using the @
symbol. In many methods, this symbol lets us refer to the value that we're transforming and define what should be done with it: we can select and return specific properties, change them, or wrap them up in a new enclosing object.
In our case, we'll use @
to provide a catch-all value for a product's category when it isn't matched against any of our other options. And because the @
symbol represents the current value being matched, that value will always match against itself!
If we encounter a category we haven't already matched against a different option, we'll stick it in the MISC
category.
Let's add that catch-all condition to our match
.
category: category->match(["gear", "ACCESSORIES"],["clothing", "APPAREL"],[@, "MISC"])
Note: If we made [@, "MISC"]
the first option in the match
method, every category would match against itself (@
) and get converted to "MISC"
. Let's keep it at the end so it catches only those values that haven't already been matched!
With our match
method in place, we should see that we've successfully updated each product's "category"
to match one of the values in our enum.
Practice
Use the mapping below to answer the next question.
category: category->match(["switch", "ELECTRONICS"],[@, "MISC"]["vase", "DECOR"],)
category
is "vase"
?category
is "switch"
?Key takeaways
- The
match
method allows us to locate instances of some value in our data, and replace them with a value that we define. - The
@
symbol is used to refer to the value we are applying a transform method to. Withmatch
, we can use@
to specify our catch-all match, and replace any values that are not matched by our other options.
Journey's end
We've covered a lot of ground! With some new methods in our back pocket, we can traverse and transform our JSON responses confidently. We hope you'll continue to share your connectors journey with us—and we'll see you next time on Odyssey!
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.