Search code examples
objective-cjsonnsdatansurl

Retrieve nested objects from JSON - Objective C


I seem to be having a small issue with the parsing through a nested JSON result. The following code works perfectly if the JSON is not nested. I'm a littler perplexed on how to proceed as every attempted (through examples of others) have failed.

So, to test this I'm using the following API from https://developer.worldweatheronline.com/page/explorer-free

I simply would like to get my current temperature (temp_c).

Below is the code calling the service. Note that I have an NSObject that will fill the data, but of course I can't seem to get to that stage. Also it is an NSMutableArray throughout. Again, I don't think that is the issue but provides context.

-(void)retrieveLocalWeatherService {
NSURL *url = [NSURL URLWithString:getLocalWeather];
NSData *data = [NSData dataWithContentsOfURL:url];

jsonArray = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];

//set up array and json call
weatherArray = [[NSMutableArray alloc]init];

//Loop through the JSON array
for (int i = 0; i< jsonArray.count; i++)
{
    //create our object
    NSString *nTemp = [[jsonArray objectAtIndex:i]objectForKey:@"temp_C"];
    NSString *nPressure = [[jsonArray objectAtIndex:i]objectForKey:@"pressure"];
    NSString *nHumidity = [[jsonArray objectAtIndex:i]objectForKey:@"humidity"];

    //Add the object to our animal array
    [weatherArray addObject:[[LocalWeather alloc]initWithtemp:(nTemp) andpressure:nPressure andhumidity:nHumidity]];
}

Here is the JSON response.

{
"data": {
    "current_condition": [
        {
            "cloudcover": "75",
            "FeelsLikeC": "31",
            "FeelsLikeF": "88",
            "humidity": "70",
            "observation_time": "05:15 AM",
            "precipMM": "0.0",
            "pressure": "1011",
            "temp_C": "28",
            "temp_F": "82",
            "visibility": "10",
            "weatherCode": "116",
            "weatherDesc": [
                {
                    "value": "Partly Cloudy"
                }
            ],
            "weatherIconUrl": [
                {
                    "value": "http://cdn.worldweatheronline.net/images/wsymbols01_png_64/wsymbol_0002_sunny_intervals.png"
                }
            ],
            "winddir16Point": "N",
            "winddirDegree": "10",
            "windspeedKmph": "41",
            "windspeedMiles": "26"
        }
    ],
    "request": [
        {
            "query": "Brisbane, Australia",
            "type": "City"
        }
    ],

I cut off the JSON service as it goes for miles, so where am I going wrong? I believe its somewhere within "for-loop" but am unsure where. I know its major node is "data" and then sub-node is "current_condition". Should I be digging through the JSON results? If what is the best approach.

BTW, I'm getting a response from the server with the entire JSON result..clearly a parsing issue on my part.

Thanks in advance! please be kind i'm a newbie.


Solution

  • You are parsing your JSON data in wrong way, you are parsing JSON directly to Array but as per your JSON format your JSON will return an NSDictionary not NSArray.

    -(void)retrieveLocalWeatherService {
            NSURL *url = [NSURL URLWithString:getLocalWeather];
            NSData *data = [NSData dataWithContentsOfURL:url];
    
            NSDictionary *weatherJson = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
    
            NSArray *currentConditionArray = [weatherJson valueForKeyPath:@"Data.current_condition"];
    
            //set up array and json call
            weatherArray = [[NSMutableArray alloc]init];
    
            //Loop through the JSON array
            for (NSDictionary *item in currentConditionArray)
            {
                //create our object
                NSString *nTemp = [item objectForKey:@"temp_C"];
                NSString *nPressure = [item objectForKey:@"pressure"];
                NSString *nHumidity = [item  objectForKey:@"humidity"];
    
                //Add the object to our animal array
                [weatherArray addObject:[[LocalWeather alloc]initWithtemp:(nTemp) andpressure:nPressure andhumidity:nHumidity]];
            }
        }