1

My purpose is to make an app (iOS) where the user can enter any combination of letters and yahoo will suggest several stocks that come closet to match that search.

My question is actually related to an older question, here: Stock ticker symbol lookup API

And answered by doing this: http://d.yimg.com/autoc.finance.yahoo.com/autoc?query=k&callback=YAHOO.Finance.SymbolSuggest.ssCallback

You get this:

YAHOO.Finance.SymbolSuggest.ssCallback({"ResultSet":{"Query":"k","Result":[{"symbol":"K","name":"Kellogg Company","exch":"NYQ","type":"S","exchDisp":"NYSE","typeDisp":"Equity"},{"symbol":"KO","name":"The Coca-Cola Company","exch":"NYQ","type":"S","exchDisp":"NYSE","typeDisp":"Equity"},{"symbol":"KRA","name":"Kraton Performance Polymers Inc.","exch":"NYQ","type":"S","exchDisp":"NYSE","typeDisp":"Equity"},{"symbol":"KMI","name":"Kinder Morgan, Inc.","exch":"NYQ","type":"S","exchDisp":"NYSE","typeDisp":"Equity"},{"symbol":"KEY","name":"KeyCorp.","exch":"NYQ","type":"S","exchDisp":"NYSE","typeDisp":"Equity"},{"symbol":"KMB","name":"Kimberly-Clark Corporation","exch":"NYQ","type":"S","exchDisp":"NYSE","typeDisp":"Equity"},{"symbol":"KRFT","name":"Kraft Foods Group, Inc.","exch":"NMS","type":"S","exchDisp":"NASDAQ","typeDisp":"Equity"},{"symbol":"KORS","name":"Michael Kors Holdings Limited","exch":"NYQ","type":"S","exchDisp":"NYSE","typeDisp":"Equity"},{"symbol":"GMCR","name":"Keurig Green Mountain, Inc.","exch":"NMS","type":"S","exchDisp":"NASDAQ","typeDisp":"Equity"},{"symbol":"KLAC","name":"KLA-Tencor Corporation","exch":"NMS","type":"S","exchDisp":"NASDAQ","typeDisp":"Equity"}]}})

But this is not a valid JSON format. The first part of the returned data is:

YAHOO.Finance.SymbolSuggest.ssCallback(

And I don't know what to do with that. When I do this:

NSDictionary *root = [NSJSONSerialization JSONObjectWithData: data
options:NSJSONReadingAllowFragments error: &parsingError];
NSLog(@"root: %@", root);

The root is null. In a normal json object I use options:kNilOptions but changed after trying to google solutions.

The error message is this:

Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (Invalid value around character 0.) UserInfo=0x7ff5637375f0 {NSDebugDescription=Invalid value around character 0.}

What should I do? Please be explicit. I've really googled like mad, but I don't understand. Thank you!

My full code is:

- (void)createSearchObj: (NSString*)searchStr {

NSString *searchString = [NSString stringWithFormat: @"http://d.yimg.com/autoc.finance.yahoo.com/autoc?query=%@&callback=YAHOO.Finance.SymbolSuggest.ssCallback", searchStr];

NSLog(@"searchString: %@", searchString);

NSURL                *url     = [NSURL URLWithString:searchString];
NSURLRequest         *request = [NSURLRequest requestWithURL:url];
NSURLSession         *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task    = [session dataTaskWithRequest:request completionHandler:^
                                 (NSData *data, NSURLResponse *response, NSError *error)
                                 {
                                     NSLog(@"ERROR: %@", error);
                                     NSLog(@"DATA: %@", data);

                                     NSError *parsingError = error;
 /*
                                     NSDictionary *root =
                                     [NSJSONSerialization JSONObjectWithData:
                                      data options:kNilOptions error: &parsingError];
*/
                                     NSDictionary *root =
                                     [NSJSONSerialization JSONObjectWithData:
                                      data options:NSJSONReadingAllowFragments error: &parsingError];

                                     NSLog(@"root: %@", root);

                                     if (!parsingError) {

                                        dispatch_async(dispatch_get_main_queue(), ^{

                                            NSDictionary *dict = [root objectForKey:@"ResultSet"];
                                            NSLog(@"dict: %@", dict);

                                        });

                                     } else {

                                         NSLog(@"Could not parse json: %@", parsingError);

                                     }

                                 }];

[task resume];
[self.view endEditing:YES];

}
Community
  • 1
  • 1
Tilo Delau
  • 103
  • 1
  • 1
  • 11

2 Answers2

0

Looks like Yahoo is putting out JSONP (JSON with padding). Sadly solutions seem to look like "take a substring of whatever's inside the parentheses and parse that."

How to parse JSONP in Objective-C?

Community
  • 1
  • 1
Rikki Gibson
  • 4,136
  • 23
  • 34
0

Answer is that this is a jsonp; json with padding and I need to parse away the extra text to make it json compliant. Thanks to rikkigibson, the solution is this:

if (data) {
          NSLog(@"data");
          NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
          NSLog(@"jsonString: %@", jsonString);

          NSRange range = [jsonString rangeOfString:@"("];
          range.location++;
          range.length = [jsonString length] - range.location - 1; // removes parens and trailing semicolon
          NSString *jsonString = [jsonString substringWithRange:range];
          NSLog(@"jsonString after cut: %@", jsonString);
          NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];

          NSError *jsonError = nil;
          NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&jsonError];
          NSLog(@"jsonResponse: %@", jsonResponse);

       if (jsonResponse) {
       // process jsonResponse as needed
       } else {
       NSLog(@"Unable to parse JSON data: %@", jsonError);
       }
       } else {
       NSLog(@"Error loading data: %@", error);
       }
       if (!parsingError) { dispatch_async(dispatch_get_main_queue(), ^{
       // Do stuff here
       });

       } else {

       NSLog(@"Could not parse json: %@", parsingError);

       }

       }];

[task resume];
[self.view endEditing:YES];

}
Tilo Delau
  • 103
  • 1
  • 1
  • 11