Pergunta

While using Mantle, is there a possibility to before returning the object we are creating (on this case via JSON) to verify that X and Y properties are not nil?

Imagine this class:

@interface Person : MTLModel <MTLJSONSerializing>

@property(nonatomic,strong,readonly)NSString *name;
@property(nonatomic,strong,readonly)NSString *age;

@end

I want a way to verify that if the JSON I received doesn't have the name (for some reason there was an issue on server's DB) I will return a nil Person, as it doesn't make sense to create that object without that property set.

Foi útil?

Solução 2

You can use the MTLJSONSerializing protocol method classForParsingJSONDictionary: to return nil rather than an invalid object:

// In your MTLModelSubclass.m
//
+ (Class)classForParsingJSONDictionary:(NSDictionary *)JSONDictionary {
    if (JSONDictionary[@"name"] == nil || JSONDictionary[@"age"] == nil) {
        return nil;
    }
    return self.class;
}

Outras dicas

Whilst you could override the initialiser. It seems more concise to override the validate: as this is called at the last stage before Mantle returns the deserialised object. Makes sense to put all your validation logic in a validate method...

See the final line of the MTLJSONAdapter

id model = [self.modelClass modelWithDictionary:dictionaryValue error:error];
return [model validate:error] ? model : nil;

This tells us that if our custom model returns NO from validate, then Mantle will discard the object.

So you could in your subclass simply perform the following:

- (BOOL)validate:(NSError **)error {
    return [super validate:error] && self.name.length > 0; 
}

Ideally in your own implementation you probably want to return an appropriate error.

The validate method will then call Foundation's validateValue:forKey:error: for every property that you registered with Mantle in JSONKeyPathsByPropertyKey. So if you want a more controlled validation setup you could also validate your data here..

In fact I don't use Mantle, but for validation I use another GitHub Library called RPJSONValidator

It tells you the type that you expect and what type the value has been arrived.

A simple example code

NSError *error;

[RPJSONValidator validateValuesFrom:json
                   withRequirements:@{
                           @"phoneNumber" : [RPValidatorPredicate.isString lengthIsGreaterThanOrEqualTo:@7],
                           @"name" : RPValidatorPredicate.isString,
                           @"age" : RPValidatorPredicate.isNumber.isOptional,
                           @"weight" : RPValidatorPredicate.isString,
                           @"ssn" : RPValidatorPredicate.isNull,
                           @"height" : RPValidatorPredicate.isString,
                           @"children" : RPValidatorPredicate.isArray,
                           @"parents" : [RPValidatorPredicate.isArray lengthIsGreaterThan:@1]
                   } error:&error];

if(error) {
    NSLog(@"%@", [RPJSONValidator prettyStringGivenRPJSONValidatorError:error]);
} else {
    NSLog(@"Woohoo, no errors!");
}

Each key-value pair describes requirements for each JSON value. For example, the key-value pair @"name" : RPValidatorPredicate.isString will place a requirement on the JSON value with key "name" to be an NSString. We can also chain requirements. For example, @"age" : RPValidatorPredicate.isNumber.isOptional will place a requirement on the value of "age" to be an NSNumber, but only if it exists in the JSON.

I use a very old version of Mantle. YMMV

You can override the [MTLModel modelWithExternalRepresentation] selector. Make sure to call [super modelWithExternalRepresentation] and then add your own code to check for validate data.

I followed a small issue opened on Mantle:

- (instancetype)initWithDictionary:(NSDictionary *)dictionaryValue error:(NSError *__autoreleasing *)error
{
    BOOL isValid = NO;
    if (self = [super initWithDictionary:dictionaryValue error:error])
    {
        isValid = ...
    }

    return isValid?self:nil;
}

So in the end just override:

- (instancetype)initWithDictionary:(NSDictionary *)dictionaryValue error:(NSError *__autoreleasing *)error
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top