Cheese1223
Cheese1223

Reputation: 107

Check if key exists in last.fm returned json

I'm writing an iOS app that uses the last.fm web services to search for albums. The following code converts the returned json to an NSArray:

results = (NSArray *)[[[json valueForKey:@"results"] valueForKey:@"albummatches"] valueForKey:@"album"];

This works fine when a search term returns a result, but the application crashes when no results are returned. This is because the key "album" doesn't exist in the json when no results are found.

How to I get my application to check if the "album" key exists in the json?

EDIT: Sample json returned when there are no results. Search string was 'asdfgasdfg'. Please note the character return under the albummatches key.

2013-03-12 14:08:00.889 MyMusicLibrary[387:1a03] {
results =     {
    "@attr" =         {
        for = asdfgasdfg;
    };
    albummatches = "\n";
    "opensearch:Query" =         {
        "#text" = "";
        role = request;
        searchTerms = asdfgasdfg;
        startPage = 1;
    };
    "opensearch:itemsPerPage" = 50;
    "opensearch:startIndex" = 0;
    "opensearch:totalResults" = 0;
};
}

EDIT 2: Sample json when results are returned:

2013-03-12 14:19:42.769 MyMusicLibrary[880:1a03] {
results =     {
    "@attr" =         {
        for = coldplay;
    };
    albummatches =         {
        album =             (
                            {
                artist = Coldplay;
                id = 1416655;
                image =                     (
                                            {
                        "#text" = "http://userserve-ak.last.fm/serve/34s/85845017.png";
                        size = small;
                    },
                                            {
                        "#text" = "http://userserve-ak.last.fm/serve/64s/85845017.png";
                        size = medium;
                    },
                                            {
                        "#text" = "http://userserve-ak.last.fm/serve/126/85845017.png";
                        size = large;
                    },
                                            {
                        "#text" = "http://userserve-ak.last.fm/serve/300x300/85845017.png";
                        size = extralarge;
                    }
                );
                mbid = "c67be398-9417-4c22-bc13-d6158029ae21";
                name = "A Rush of Blood to the Head";
                streamable = 1;
                url = "http://www.last.fm/music/Coldplay/A+Rush+of+Blood+to+the+Head";
            },
                            {
                artist = Coldplay;
                id = 1984;
                image =                     (
                                            {
                        "#text" = "http://userserve-ak.last.fm/serve/34s/87203265.png";
                        size = small;
                    },
                                            {
                        "#text" = "http://userserve-ak.last.fm/serve/64s/87203265.png";
                        size = medium;
                    },
                                            {
                        "#text" = "http://userserve-ak.last.fm/serve/126/87203265.png";
                        size = large;
                    },
                                            {
                        "#text" = "http://userserve-ak.last.fm/serve/300x300/87203265.png";
                        size = extralarge;
                    }
                );
                mbid = "8e602038-c0f2-3c2d-9068-a1a3daca493d";
                name = Parachutes;
                streamable = 1;
                url = "http://www.last.fm/music/Coldplay/Parachutes";
            }
        );
    };
    "opensearch:Query" =         {
        "#text" = "";
        role = request;
        searchTerms = coldplay;
        startPage = 1;
    };
    "opensearch:itemsPerPage" = 2;
    "opensearch:startIndex" = 0;
    "opensearch:totalResults" = 375;
};
}

Upvotes: 1

Views: 990

Answers (3)

Paul.s
Paul.s

Reputation: 38728

There are two ways you could go about this

  1. Assuming that the "opensearch:totalResults" is in fact the correct results count then you could use this value to determine if you have results or not and then use

    NSArray *results = nil;
    
    if ([[json valueForKeyPath:@"results.opensearch:totalResults"] intValue] > 0) {
      results = [json valueForKeyPath:@"results.albummatches.album"];
    }
    
  2. Check whether you have a string or an array before processing it

    id albummatches = [json valueForKeyPath:@"results.albummatches"];
    
    // is this a dictionary or a string?
    // You can either ask if it implements the interface or ask what class it is. I prefer the first
    BOOL isDictionary = [albummatches respondsToSelector:@selector(objectForKey:)];
    
    // or
    BOOL isDictionary = [albummatches isKindOfClass:[NSDictionary class]];
    
    if (isDictionary) {
      results = [albummatches objectForKey:@"album"];
    }
    

Upvotes: 1

Cheese1223
Cheese1223

Reputation: 107

Someone posted a really good answer earlier, but it was then removed. It helped a lot with this though, and I modified it slightly to get the code below, which now works.

            NSDictionary *resultsDict = [json valueForKey:@"results"];
        if (resultsDict != nil) {
            //Checks to see if any results are returned
            NSDictionary *albumMatchesDict = [resultsDict valueForKey:@"albummatches"];
            NSString *albumMatchesString = [resultsDict valueForKey:@"albummatches"];
            NSCharacterSet *set = [NSCharacterSet whitespaceCharacterSet];
            albumMatchesString = [[albumMatchesString description] stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]];

            if ([[albumMatchesString stringByTrimmingCharactersInSet:set] length] != 0) {
                results = (NSArray *) [albumMatchesDict valueForKey:@"album"];
            }
        }

Upvotes: 0

Anoop Vaidya
Anoop Vaidya

Reputation: 46543

Check:

if([[json[@"result"][@"albummatches"] allKeys] containsObject:@"album"]==YES){

    //do your work here
}

Upvotes: 0

Related Questions