Question

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
Was it helpful?

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.

OTHER TIPS

Create an NSNull+JSON category and import that in the JSONModel.m or in the {ProjectName}-Prefix.pch

#import <Foundation/Foundation.h>

@interface NSNull (JSON)

@end

#import "NSNull+JSON.h"

@implementation NSNull (JSON)

- (NSUInteger)length { return 0; }

- (NSInteger)integerValue { return 0; };

- (NSInteger)intValue { return 0; };

- (float)floatValue { return 0; };

- (NSString *)description { return @"0(NSNull)"; }

- (NSArray *)componentsSeparatedByString:(NSString *)separator { return @[]; }

- (id)objectForKey:(id)key { return nil; }

- (BOOL)boolValue { return NO; }

@end

I have been using that in many of my projects. I prefer to use this process so even if my server introduced any new JSON key for the API response, JSON parsing will still work without any crash or issue...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top