views:

24

answers:

2

Hi all

I'm afraid I'm a newbie to objective-c programming, and I am having a problem that I have spent all day trying to figure out and I cannot, so I am humbly asking you guys if anyone can help.

I am trying to read the details from a JSON page online (for instance a local services directory) and have installed the JSON library into Xcode and it seems to work fine. I'm developing for the iPhone by the way, and have the latest versions all installed.

The problem is, what with me being a newb and all, I seem unable to retrieve all the information I need from the JSON file.

the JSON data I am testing with is this:

"testlocal_response" =     {
        header =         {
            query =             {
                business = newsagent;
                location = brighton;
                page = 1;
                "per_page" = 1;
                "query_path" = "business/index";
            };
            status = ok;
        };
        records =         (
                        {
                address1 = "749 Rwlqsmuwgj Jcyv";
                address2 = "<null>";
                "average_rating" = 0;
                "business_id" = 4361366;
                "business_keywords" = "<null>";
                "business_name" = "Gloucester Newsagents";
                "data_provider_id" = "<null>";
                "display_details" = "<null>";
                "distance_in_miles" = "0.08";
                fax = "<null>";
                gridx = "169026.3";
                gridy = "643455.7";
                "image_url" = "<null>";
                latitude = "50.82718";
                "logo_path" = Deprecated;
                longitude = "-0.13963";
                phone = 97204438976;
                postcode = "IY1 6CC";
                "reviews_count" = 0;
                "short_description" = "<null>";
                "touch_url" = "http://www.test.com/business/list/bid/4361366";
                town = BRIGHTON;
                url = "<null>";
            }
        );
    };
}

Now, in my code ViewController.m page, in the 'connectionDidFinishLoading' area I have added:

  NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
 [responseData release];

 // make sure JSON has all been pulled in
        NSLog(@"This is from the JSON page:\n");
 NSLog(responseString);
 NSError *error;
 SBJSON *json = [[SBJSON new] autorelease];

        // using either of these seems to make no difference?
 NSDictionary *touchDirect = [json objectWithString:responseString error:&error];
 //NSArray *touchDirect = [json objectWithString:responseString error:&error];
 [responseString release]; 

 if (touchDirect == nil)
  label.text = [NSString stringWithFormat:@"JSON parsing failed: %@", [error localizedDescription]];
 else {  
  NSMutableString *text = [NSMutableString stringWithString:@"Test directory details:\n"];

  [text appendFormat:@"%@\n", [[[[touchDirect objectForKey:@"testlocal_response"] objectForKey:@"header"] objectForKey:@"query"] objectForKey:@"business"]];

  label.text =  text;

Testing this I get the value for the business ('newsagent') returned, or location ('brighton') which is the correct. My problem is, I cannot go further into the JSON. I don't know how to pull out the result for the actual 'records' which, in the test example there is only one of but can be more divided using brackets '(' and ')'.

As soon as I try to access the data in these record areas (such as 'address1' or 'latitude' or 'postcode') it fails and tells me 'unrecognized selector sent to instance'

PLEASE can anyone tell me what I'm doing wrong?! I've tried so many different things and just cant get any further! I've read all sorts of different things online but nothing seems to help me.

Any replies deeply appreciated. I posted up a question on iPhone SDK too but havent had a useful response yet.

many thanks,

-Robsa

A: 

Have you validated your JSON?

It's not clear how you are trying to access the objects that you say are erroring. The specific line(s) you are having trouble with would be helpful.

It's usually easier to set a pointer to the dictionary you are going to be accessing for readability..

NSDictionary *records = [[objectForKey:@"testlocal_response"] objectForKey@"records"];

then...

NSString *businessName = [records objectForKey:@"business_name"];
float latitude = [[records objectForKey:@"latitude"] floatValue];
Nick
A: 

Hi guys,

Well, I finally sorted it out! I put the records in an NSString, which I could then access using objectAtIndex. Here is the main Viewcontroller.m code for it:

- (void)viewDidLoad {   
    [super viewDidLoad];

    responseData = [[NSMutableData data] retain];       
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"*URL TO JSON DATA HERE*"]];
    [[NSURLConnection alloc] initWithRequest:request delegate:self];               
    NSMutableArray *touchDirect = [json objectWithString:responseString error:&error]; 
    NSString *touchRecord = [[touchDirect objectForKey:@"touchlocal_response"] objectForKey:@"records"];

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    [responseData setLength:0];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    [responseData appendData:data];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    label.text = [NSString stringWithFormat:@"Connection failed: %@", [error description]];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {      
    [connection release];

    NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
    [responseData release];
    NSError *error;
    SBJSON *json = [[SBJSON new] autorelease];
    //Retrieves the JSON header Data, returning info such as 'status' [which should return 'ok']
    NSMutableArray *touchDirect = [json objectWithString:responseString error:&error]; 
    //Puts the records returned into a string called touchRecord
    NSString *touchRecord = [[touchDirect objectForKey:@"touchlocal_response"] objectForKey:@"records"];
    [responseString release];   

    // test results   
    [text appendFormat:@" Address: %@\n", [[touchRecord objectAtIndex:0] objectForKey:@"address1"]];
    [text appendFormat:@" Phone:   %@\n", [[touchRecord objectAtIndex:0] objectForKey:@"phone"]];
    [text appendFormat:@" Address Data record 2: %@\n", [[touchRecord objectAtIndex:1] objectForKey:@"address1"]];
    [text appendFormat:@" Phone Data record 2:   %@\n", [[touchRecord objectAtIndex:1] objectForKey:@"phone"]];

This now seems to work fine. I also have a if..else if statement to catch errors now. Does this code look Ok?

Thanks for the tip, Nick - I was just trying to get the output right before tidying the code up. I am using an NSMutableArray to put my JSON into initially, is this OK? What is the benefit of putting it into an NSDictionary?

regards,

Robsa

Robsa