Verify each property before returning an object

When using Mantle, is it possible to check that the X and Y properties are not zero before returning the created object (in this case, via JSON)?

Imagine this class:

@interface Person : MTLModel <MTLJSONSerializing> @property(nonatomic,strong,readonly)NSString *name; @property(nonatomic,strong,readonly)NSString *age; @end 

I want to check that if the JSON I received does not have name (for some reason there was a problem with the server database), I will return it to nil Person, since it does not make it to create this object without this set of properties.

+8
ios objective-c github-mantle
source share
5 answers

You can use the protocol method MTLJSONSerializing classForParsingJSONDictionary: to return null 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; } 
+1
source share

For now, you can override the initializer. It seems more concise to override validate: as it is called in the last step before Mantle returns the deserialized object. It makes sense to put all your validation logic in the validate method ...

See the final line MTLJSONAdapter

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

This tells us that if our user model returns NO from validate , then Mantle discards the object.

Thus, you can simply do the following in your subclass:

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

Ideally, in your own implementation, you probably want to return the corresponding error.

The validate method then calls Foundation validateValue:forKey:error: for each property that you registered with Mantle in JSONKeyPathsByPropertyKey . Therefore, if you need a more controlled verification setting, you can also check your details here.

+3
source share

I don't actually use Mantle, but for verification I use another GitHub library called RPJSONValidator

It tells you the type that you are expecting, and which type got the value.

Simple sample 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 and value pair describes the requirements for each JSON value. For example, a key-value pair @"name" : RPValidatorPredicate.isString will put the requirement in a JSON value with the key "name" as NSString . We can also knit requirements. For example, @"age" : RPValidatorPredicate.isNumber.isOptional will place a requirement for the value of "age" in the value of NSNumber , but only if it exists in JSON.

0
source share

I am using a very old version of Mantle. Ymmv

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

0
source share

I followed the little issue open in 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 
0
source share

All Articles