Mo Moosa
Mo Moosa

Reputation: 947

Google Search with iOS using JSON

Update

It appears resultField is the one that has no value. Will look into this, but I'd still appreciate any advice.

Original Post

I've been set the task of coming up with a basic iOS application that simply makes a search request and then displays the results for university work. I tried to use the Google Custom Search engine but could never get it to work on the iPhone so I've had to resort to the depreciated Google Web Search API (The lecturer is okay with this).

Now, I'm able to make the request, and it returns the JSON data as intended, which I now must parse, I think. Sadly I only have a week to do this, which is crazy as I've never worked with JSON before.

What I'd like is if someone could help me get off the ground with a pointer or two in how to get even just a basic parsing of the JSON data.

I've looked around on Stackoverflow and saw some things that might be helpful like the breakdown structure in the selected answer here.

The person put this together, which when shown in the code makes some sense to me:

A great structure explanation

dictionary (top-level)
     sethostname (array of dictionaries)
         dictionary (array element)
            msgs (string)
            status (number)
            statusmsg (string)
            warns (array)
                ??? (array element)

Sadly I can't even begin to do the same with the code generated in my app. It takes the form similar to this example code, courtesy of google - I'm no Paris Hilton fan!

Example code from Google.

{"responseData": {
 "results": [
  {
   "GsearchResultClass": "GwebSearch",
   "unescapedUrl": "http://en.wikipedia.org/wiki/Paris_Hilton",
   "url": "http://en.wikipedia.org/wiki/Paris_Hilton",
   "visibleUrl": "en.wikipedia.org",
   "cacheUrl": "http://www.google.com/search?q\u003dcache:TwrPfhd22hYJ:en.wikipedia.org",
   "title": "\u003cb\u003eParis Hilton\u003c/b\u003e - Wikipedia, the free encyclopedia",
   "titleNoFormatting": "Paris Hilton - Wikipedia, the free encyclopedia",
   "content": "\[1\] In 2006, she released her debut album..."
  },
  {
   "GsearchResultClass": "GwebSearch",
   "unescapedUrl": "http://www.imdb.com/name/nm0385296/",
   "url": "http://www.imdb.com/name/nm0385296/",
   "visibleUrl": "www.imdb.com",
   "cacheUrl": "http://www.google.com/search?q\u003dcache:1i34KkqnsooJ:www.imdb.com",
   "title": "\u003cb\u003eParis Hilton\u003c/b\u003e",
   "titleNoFormatting": "Paris Hilton",
   "content": "Self: Zoolander. Socialite \u003cb\u003eParis Hilton\u003c/b\u003e..."
  },
  ...
 ],
 "cursor": {
  "pages": [
   { "start": "0", "label": 1 },
   { "start": "4", "label": 2 },
   { "start": "8", "label": 3 },
   { "start": "12","label": 4 }
  ],
  "estimatedResultCount": "59600000",
  "currentPageIndex": 0,
  "moreResultsUrl": "http://www.google.com/search?oe\u003dutf8\u0026ie\u003dutf8..."
 }
}
, "responseDetails": null, "responseStatus": 200}

This is the code so far, which as you'll learn quickly does not really do much else than return code similar to the code above.

  **My code.** 


 // query holds the search term
query = [query stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

//append theQuery with search URL
NSString *tempString = [NSString stringWithFormat:@"%@/%@", @"https://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=", theQuery];


//Create NSURL out of tempString
NSURL *url = [NSURL URLWithString:tempString];


// Create a request object using the URL.
NSURLRequest *request = [NSURLRequest requestWithURL:url];

// Prepare for the response back from the server
NSHTTPURLResponse *response = nil;
NSError *error = nil;

    NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];


    NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONWritingPrettyPrinted error:&error];

    NSDictionary* resultField = [NSDictionary dictionaryWithDictionary:[dictionary objectForKey:@"results"]];

// Send a synchronous request to the server (i.e. sit and wait for the response)

// Check if an error occurred
if (error != nil) {
    NSLog(@"%@", [error localizedDescription]);
    // Do something to handle/advise user.
}

// Convert the response data to a string.
NSString *responseString = [[NSString alloc] initWithData:responseData  encoding:NSUTF8StringEncoding];

    NSArray *results = [dictionary objectForKey:@"results"];
    //set label's text value to responseString's value.
endLabel.text = responseString;

Now the main issue I've encountered is that the results array is null all the time. I could really do with a point in the right direction here. Thank you.

Upvotes: 3

Views: 2297

Answers (2)

Rudolf Real
Rudolf Real

Reputation: 2028

There is no need to create a new dictionary each time. For easier reading I'd recommend something like:

[[dictionary objectForKey:@"responseData"] objectForKey:@"results"]

There you have the array of results. You can then add

[ [dictionary objec...] objectAtIndex:0]

Upvotes: 0

rickster
rickster

Reputation: 126167

It looks like you're having trouble traversing the data structure parsed out of the JSON.

    NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONWritingPrettyPrinted error:&error];

Assuming the data you passed in is good, this dictionary contains the top-level structure. It has three keys responseData, responseDetails, and responseStatus. (You could see this by NSLogging the dictionary.)

You're then querying that dictionary for the key results. It doesn't exist, so your resultField variable is set to nil. The dictionary's value for the key responseData is another dictionary which does contain a key results -- you need that middle step.

Also, the value for the results key in that second dictionary is an array (of more dictionaries), not a dictionary itself.

Upvotes: 3

Related Questions