youtube-apijsonmodel

JSONModel arrayOfModelsFromDictionaries -- error when key is SOMETIMES missing


So I'm just getting started with the youtube data API and JSONModel. Using their YouTubeBrowserDemo as my starting point: https://github.com/JSONModel/YouTubeBrowserDemo.

So it's working fine except sometimes the MediaThumnail entry for certain videos doesn't have a time entry. Some returned videos have them, some don't. I'm fine with this and can of course write simple checks when I'm displaying the data, but when arrayOfModelsFromDictionaries is called to convert the returned JSON to my models, I get the following error and none of the JSON is converted if only one (or more) of the time entries are missing:

[JSONModel.m:205] Incoming data was invalid [MediaThumbnail initWithDictionary:]. Keys missing: {(
    time
)}

How do I make this conversion NOT an all-or-nothing conversion? Some kind of conditional check when mapping? Or is there a different JSONModel method that already does this?


Here's the API call and attempt to convert the resulting JSON:

 [JSONHTTPClient getJSONFromURLWithString:searchURL
                                  completion:^(NSDictionary *json, JSONModelError *err) {


                                      //got JSON back
                                      NSLog(@"Got JSON from web: %@", json);

                                      if (err) {

                                          NSLog(@"err = %@",err);



                                          [[[UIAlertView alloc] initWithTitle:@"Error"
                                                                      message:[err localizedDescription]
                                                                     delegate:nil
                                                            cancelButtonTitle:@"Close"
                                                            otherButtonTitles: nil] show];
                                          return;
                                      }




                                      //initialize the models 
                                      // THIS IS WHERE IT SOMETIMES RETURNS OBJECTS INTO SELF.OBJECTS IF ALL THE MEDIATHUMBNAILS AHVE TIME ENTRIES, OR NOTHING IF ONE OR MORE ARE MISSING
                                      self.objects = [VideoModel arrayOfModelsFromDictionaries:
                                                      json[@"feed"][@"entry"]
                                                      ];




                                      if (self.objects) {
                                          NSLog(@"Loaded successfully models");

                                      }

Here's my VideoModel.h is close to theirs - only one added property:

@interface VideoModel : JSONModel

@property (strong, nonatomic) NSString* title;
@property (strong, nonatomic) NSArray<VideoLink>* link;
@property (strong, nonatomic) NSArray<MediaThumbnail>* thumbnail;
@property (strong, nonatomic) NSArray<Author>* author;

@end

VideoModel.m:

@implementation VideoModel

+(JSONKeyMapper*)keyMapper
{
    return [[JSONKeyMapper alloc] initWithDictionary:@{
            @"media$group.media$thumbnail":@"thumbnail",
            @"title.$t": @"title"
            }];
}

@end

And my MediaThumnail.h:

@interface MediaThumbnail : JSONModel

@property (strong, nonatomic) NSURL* url;
@property (assign, nonatomic) int width;
@property (assign, nonatomic) int height;
@property (strong, nonatomic) NSString* time;

@end

MediaThumnail.m:

@implementation MediaThumbnail

@end

Solution

  • It's very easy to make some of your model's properties optional with JSONModel - have a look for an example here (more examples about different features on the same page):

    https://github.com/icanzilb/JSONModel#optional-properties-ie-can-be-missing-or-null

    All in all what you need to do is add the <Optional> protocol to your property, like so:

    @property (strong, nonatomic) NSString<Optional>* time;
    

    That's it. Don't forget when using the property to check first if it's nil or has a value.