Skip to content
This repository has been archived by the owner on Aug 30, 2019. It is now read-only.

Configuration Options

pashields edited this page Jun 20, 2012 · 9 revisions

In general, little to no configuration is necessary to use ClassMapper (or at least we try to make it that way). In certain cases though, we can't automagically fix it for you, so we've try to give you some easy ways to deal with those cases.

Key -> Class Mapping

In cases where your class is using an NSArray or NSDictionary to hold complex (non-primative) objects, key mapping saves the day. To create the mapping we use the following method:

- (void)mapKey:(NSString*)key toClass:(Class)class;

To continue with the example from the README, we would add a mapping between the "foos" key and the Foo class.

[[MapperConfig sharedInstance] mapKey:@"foos" toClass:[Foo class]];

So now, when we get to an NSDictionary (represented here as json) object like

{"cats" : "awesome", "dogs" : "pretty rad", "hedgehogs" : "OMFG", "foos" : [{"str" : "not an animal"}]}

We know that the array under the "foos" key is filled with objects that can be deserialized to your class, not just NSDictionary.

Key <-> Key mapping

Sometimes a service you are interacting with will use naming conventions you find disturbing, incorrect, or annoying. In those situations, ClassMapper let's you create bidirectional mappings between keys/property names. So if your service is giving you

{"this_key" : "Cause tonight we're gonna party like it's 1999"}

But you want to use camelCase, you can configure the mapper to handle this for you.

[[MapperConfig sharedInstance] mapPropertyName:@"this_key" toOtherName:@"thisKey"];

Then your dictionaries can use "this_key" as the key, but your object can have a thisKey attribute. Note that this is bidirectional, so A) it makes no difference the order in which the keys are passed to the above method and B) if you later created an object with a property name this_key, it would always be translated to "thisKey" for dictionaries.

It's recommended to keep these key mappings in an external (configuration) file. Plists work pretty well for this, and are a good strategy. This gist shows an example of MapperConfig category that adds the ability to read from a property list structured à la:

	<key>this_key</key>
	<string>thisKey</string>

Property class based pre/post processor blocks

Many destination data formats have limited data types in comparison to the classes we have available to us in cocoa. As a result, you may find yourself receive data as one class, but wanting to store it in a property of another class. A canonical example of this sort of thing is serialized dates. Say we have a class with an NSDate property:

@interface DateHolder : NSObject
@property(nonatomic, strong)NSDate *date;
@end

But let's assume that we are getting data like this dictionary:

NSDictionary *dict = [NSDictionary dictionaryWithObject:@"2001-01-01 GMT" forKey:@"date"];

With a quick preprocessor block, we can convert it:

[[MapperConfig sharedInstance] preProcBlock:^id(id propertyValue) {
    NSDateFormatter *df = [[NSDateFormatter alloc] init];
    [df setDateFormat:@"yyyy-MM-dd zzz"];
    return [df dateFromString:propertyValue];
} forPropClass:[NSDate class]];

DateHolder *dateHolder = [ClassMapper deserialize:dict toClass:[DateHolder class]];
dateHolder.date; // NSDate @ 2001-01-01 GMT

The particularly cool part about this is that it's totally extensible. As long as your API is feeding you consistently formatted data, you can easily convert it.

Postprocessor blocks work the same way, so you after adding the above block, you might add the following as well:

[[MapperConfig sharedInstance] postProcBlock:^id(id propertyValue) {
    NSDateFormatter *df = [[NSDateFormatter alloc] init];
    [df setDateFormat:@"yyyy-MM-dd zzz"];
    return [df dateFromString:propertyValue];
} forPropClass:[NSDate class]];

This way, when serialize is called, the process gets reversed and the data is sent back the server in the same format it was sent in.

By default these blocks are applied to any properties that are the same as the propClass or are a subclass of propClass. This behavior can be altered using MapperConfig's EXACT_CLASS_MATCH macro.