krzysztofzablocki / PropertyMapper

Property mapping for Objective-C iOS apps.
http://merowing.info
MIT License
1.13k stars 81 forks source link

Support for compound property? #43

Closed lxcid closed 9 years ago

lxcid commented 9 years ago

I was wondering, how would I support compound property, for example, if the values of latitude and longitude are in the root dictionary and I want them to create a CLLocation instance. I couldn't thought of an elegant way to do it though except falling back to hand crafting loading.

Also, I was wondering if there's support for explicitly ignoring fields.

krzysztofzablocki commented 9 years ago
  1. Boxing or KZCall -> https://github.com/krzysztofzablocki/KZPropertyMapper#advanced-usage
  2. Ignoring is automatic if you don't specify mapping, not sure what else you'd like to do here?
lxcid commented 9 years ago

Thanks for the response man! :D Though I still have some enquiries, sorry!

1) I think boxing/call only for 1 key to 1 property mapping though. I see that KZList allows 1 key to many properties mapping. I couldn't really figure out how to do boxing/call for many keys to 1 property mapping though.

e.g. for the following JSON

{
    "id" : "12345",
    "name" : "Singapore",
    "latitude" : 1.35,
    "longitude" : 103.81
}
NSDictionary *mapping = @{
    @"id" : KZProperty(identifier),
    @"name" : KZProperty(name),
    @"latitude" : KZCall(latLngToCLLocation:forKey:, location),
    @"longitude" : KZCall(latLngToCLLocation:forKey:, location),
};

Since the order of execution of the property mapper is undefined, the only solution I could think of is to implement something similar to the following latLngToCLLocation:forKey: method:

- (CLLocation *)latLngToCLLocation:(NSNumber *)latOrLng forKey:(NSString *)key {
    static NSString *prevKey = nil;
    static NSNumber *prevLatOrLng = nil;
    if (prevKey && prevLatOrLng) {
        CLLocation *location = nil;
        // TODO: (me@lxcid.com) Create location from lat & lng.
        prevKey = nil;
        prevLatOrLng = nil;
        return location;
    } else {
        prevKey = key;
        prevLatOrLng = latOrLng;
        return nil;
    }
}

The solution I current have as you can see is pretty error prone and have multiple area of failure which would have to be guarded against. I'm just wondering if there's better solution for many keys to 1 property mapping. :) It not a showstopper cause I can always revert to manual mapping.

2) I love that it reports unmapped key, I can see myself skipping KZPropertyMapper for some more complex scenario like the above.

Thanks for this great gem, I really like it.

krzysztofzablocki commented 9 years ago

Ah, so boxing and KZCall are meant to be used for sub-objects, if you had those properties inside a root then you'd just use that root as the key e. g. something like this

{
    "id" : "12345",
    "name" : "Singapore",
    "location" : {
       "latitude" : 1.35,
       "longitude" : 103.81
    }
}
@"location" : KZCall(CLLocationFromLocation:, location)

In your case, I'd just do a dynamic / lazy configured public property, then you can keep normal mapping for lat/lon inside your class, but public interface would use CLLocation ?

lxcid commented 9 years ago

Ah thanks! I didn't thought of that! Haha! I'm over thinking it!