Filter API Responses with Output Filters for the iOS SDK


Temboo can help you reduce the complexity of API responses. Just specify one or more Output Filters when you call a Choreo.

What's an Output Filter?

It’s a filter that returns only the data that you care about!

Many APIs return a lot of complex JSON or XML data that can be difficult to parse. Let's take a look at how we can use Output Filters with the iOS SDK to make API responses easier to work with.

Before You Begin

Make sure that you've been through the iOS getting started tutorial. In the following steps, we'll build upon that tutorial by adding Output Filters.

FILTERING API RESPONSES

1In the getting started tutorial, we printed out the Latitude, Longitude and the full Response. To setup our Output Filters, let's print out all of the returned data at once. Go ahead and replace the Latitude, Longitude and Response NSLog statements with the following:

NSLog(@"%@", [result getOutputs]);

2Run the code and take a look at the console. See the XML response? There's a lot of data!

3What if the only information we need for our application is the formatted_address, and a collection of individual address_components that make up that address? Introducing Output Filters will allow us to extract only those data elements by adding just two lines of code. Add the following lines before the [geocodeByAddressChoreo executeWithInputs:geocodeByAddressInputs delegate:self]; method:

// Get the full address as a string
[geocodeByAddressInputs addOutputFilter:@"address" withPath:@"/GeocodeResponse/result/formatted_address" andVariableSource:@"Response"];
// Get the components of the address as a list
[geocodeByAddressInputs addOutputFilter:@"components" withPath:@"/GeocodeResponse/result/address_component/long_name" andVariableSource:@"Response"];

4Run the code again and take a look at the console. You should see the full address, as well as a collection of the long_name components from the XML.

    address = "104 Franklin Street, New York, NY 10013, USA";
    components =     (
        104,
        "Franklin Street",
        "Lower Manhattan",
        Manhattan,
        "New York",
        "New York County",
        "New York",
        "United States",
        10013
    );

How Did we do it?

Before showing some neat tricks to access the individual elements in the data, let's take a look at how the filter is created. As we saw above, each Output Filter is constructed with three parameters, in the format:

[ChoreoInputSet addOutputFilter:@"result_label" withPath:@"data_path" andVariableSource:@"choreo_output"];

It may look confusing at first, but let’s step through recreating the two Output Filters from scratch to understand what's happening.

1A ChoreoInputSet object is used to specify the inputs that will be passed to the Choreo. Output Filters are also a type of Choreo input, so we'll add our inputs to the ChoreoInputSet object. To find the input set that we used to add the Geocoding Output Filters, just look back at the following line in your code:

// Get Inputs object for the choreo
TMBGoogle_Geocoding_GeocodeByAddress_Inputs *geocodeByAddressInputs = [geocodeByAddressChoreo newInputSet];

After identifying the input that we'd like to filter, add addOutputFilter as shown below.

geocodeByAddressInputs addOutputFilter:@"result_label" withPath:@"data_path" andVariableSource:@"choreo_output"];

2A result_label is anything we want it to be! It can be data123 or apple or Homer, as long as each output filter has a unique result_label of numbers or letters. This is how we tell Temboo to label a piece of result information when it is returned. In our example, we called our collection of address elements “components”. We called the full address "address".

3The data_path is used to identify, via XPath or a JSON path, the location of the particular item(s) that you want your Output Filter to return. For a more in depth explanation of data paths and data types, check out our guide on JSON & XML for Output Filters. Here are the paths that we used when specifying our Output Filters earlier.

 /GeocodeResponse/result/address_component/long_name
 /GeocodeResponse/result/formatted_address

4The Choreo_output is the name of the Choreo output data that we're applying our output filter to. These names can be found in each Choreo's output section on our website. In most cases, the relevant Choreo output name will be Response, like in the screenshot below. However, as you can see we can also retrieve Latitude and Longitude in this particular Choreo.

Yahoo! Weather Choreo Outputs

5When we combine all of this information, we have two Output Filters. One returns only the full formatted address as a string, and another returns a collection of elements that make up the address as a list.

// add an output filter to extract the full address
[geocodeByAddressInputs addOutputFilter:@"address" withPath:@"/GeocodeResponse/result/formatted_address" andVariableSource:@"Response"];
// add an output filter to extract the collection of address long_name components
[geocodeByAddressInputs addOutputFilter:@"components" withPath:@"/GeocodeResponse/result/address_component/long_name" andVariableSource:@"Response"];

Making use of the data

Previously, we printed all of the filtered outputs together. However, it can be even more useful to access each element individually.

We noted before that the "components" data is a collection of individual elements that make up the address. To access those elements, we'll use a for loop to iterate through a list of elements retrieved from the [results getOutputArrayByName:@"components"] method and print each on a new line. Let's give it a try:

1Replace the line that calls NSLog(@"%@", [result getOutputs]); with the code below:

for(id c in [result getOutputArrayByName:@"components"]) {
    NSLog(@"component: %@", c);
}

2Since there is only one piece of data contained in the filter "address", we can simply print the data using the [result getOutputByName:(NSString *)] method. Add the following line, beneath the for loop you created in the last step:

NSLog(@"%@", [result getOutputByName:@"address"]);

3If you run the code and look at the console, you'll see each of the individual elements from our address as well as the full formatted address:

the results of our Output Filters printed to the console

Here's the full code

The complete code takes advantage of two Output Filters. It should look like this:

#import <Foundation/Foundation.h>
#import "TMBGoogle.h"
#import "TMBChoreography.h"
#import "TMBTembooSession.h"

@interface GeocodeByAddress : NSObject <TMBChoreographyDelegate>
-(void)runGeocodeByAddressChoreo;
-(void)choreographyDidFailWithError:(NSError*)error;
-(void)choreographyDidFinishExecuting:(TMBGoogle_Geocoding_GeocodeByAddress_ResultSet*)result;
@end

@implementation GeocodeByAddress

-(void)runGeocodeByAddressChoreo {
    // Instantiate the Choreo, using a previously instantiated TembooSession object, eg:
    TMBTembooSession *session = [[TMBTembooSession alloc] initWithAccount:@"ACCOUNT_NAME" appKeyName:@"APP_NAME" andAppKeyValue:@"APP_KEY"];

    // Create the Choreo object using your Temboo session
    TMBGoogle_Geocoding_GeocodeByAddress *geocodeByAddressChoreo = [[TMBGoogle_Geocoding_GeocodeByAddress alloc] initWithSession:session];
	
    // Get Inputs object for the Choreo
    TMBGoogle_Geocoding_GeocodeByAddress_Inputs *geocodeByAddressInputs = [geocodeByAddressChoreo newInputSet];
    
    // Set inputs
    [geocodeByAddressInputs setAddress:@"104 Franklin St, 10013"];
    
    // add an output filter to extract the full address
    [geocodeByAddressInputs addOutputFilter:@"address" withPath:@"/GeocodeResponse/result/formatted_address" andVariableSource:@"Response"];
    // add an output filter to extract the collection of address long_name components
    [geocodeByAddressInputs addOutputFilter:@"components" withPath:@"/GeocodeResponse/result/address_component/long_name"     andVariableSource:@"Response"];
    
    // Execute Choreo specifying this class as the choreo delegate
    [geocodeByAddressChoreo executeWithInputs:geocodeByAddressInputs delegate:self];
}

// TMBChoreographyDelegate method implementation - handle Choreo errors
-(void)choreographyDidFailWithError:(NSError*)error {
    // Log error to the console
    NSLog(@"Error - %@", error);
}

// TMBChoreographyDelegate method implementation - Choreo executed successfully
-(void)choreographyDidFinishExecuting:(TMBGoogle_Geocoding_GeocodeByAddress_ResultSet*)result {
    // Log results to the console
    // NSLog(@"%@", [result getOutputs]);
   
    //Loop through a collection of items and log Output Filter results to the console
    for(id c in [result getOutputArrayByName:@"components"]) {
        NSLog(@"component: %@", c);
    }
    
    //Log individual string from Output Filter results to the console
    NSLog(@"%@", [result getOutputByName:@"address"]);
}
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // Create a new instance of our class
        GeocodeByAddress *tutorial = [[GeocodeByAddress alloc] init];
        
        // Run it
        [tutorial runGeocodeByAddressChoreo];
        
        // Only needed for command line tools, this simply keeps the program from exiting immediately
        [[NSRunLoop currentRunLoop] run];
    }
    return 0;
}

You should now see individual outputs for each of the address "components" as a list, and the full "address" as a string printed to the serial monitor.

What's Next?

We've filtered some data! You can specify as many Output Filters as you need for each Choreo, so why not try adding your own third filter to this example? If you'd like to try something different, you can try filtering the output from any of our 2000+ Choreos.

Once you've got your code up and running, you're ready to move on and do more. From monitoring your running applications, to moving your generated Temboo code to your preferred development environment and sharing it with colleagues, collaborators and friends - we've got you covered.

Need Help?

We're always happy to help. Just email us at support@temboo.com, and we'll answer your questions.


Back