aryaxt / OCMapper

Objective-C library to easily map NSDictionary to model objects, works perfectly with Alamofire. ObjectMapper works similar to GSON
MIT License
347 stars 45 forks source link

Support for custom factory methods #9

Closed laenger closed 9 years ago

laenger commented 9 years ago

In this particular situation I need to map an array to a nested object.

From
{p:[3,4]}
To
X
_p
__a
__b

The Jackson Java library supports custom factory methods, e.g., through the @JsonCreator annotation, that allow me to realize such a mapping in the following way. Jackson then searches for a suitable factory method whenever it has to map int[] to P. Support for some sort of factory methods would be a powerful feature.

public class X {
    @JsonProperty("p")
    private P p;
}

public class P {
    private int a;
    private int b;

    public P(int a, int b) {
        this.a= a;
        this.b= b;
    }

    @JsonCreator
    public static P fromValue(int[] array) {
        return new P(array[0], array[1]);
    }
}
aryaxt commented 9 years ago

Good Idea, will add this as a feature. Can you confirm that below is the type of feature you were talking about?

JSON

{
     "country" : "COUNTRY_NAME"
}

Model

@implementation User
      @property (nonatomic, strong) Country *country;
@end

Usage

[mappingProvider mapFromKey:@"country" toProperty:@"country" forClass:[User class] withTransformer:^(id countryStringInDictionary) {
    Country *country = [[Country alloc] initWithName:countryStringInDictionary];
    return country;
]};
laenger commented 9 years ago

The difference between the Java example and your suggestion is that you are specifiying the mapping configuration through the parent object (User in this case) instead of the object itself (Country). Therefore one would have to repeat the configuration for other Objects with a country property (say, Business). However, I believe that your approach is consistent with the existing mapping provider API and I am not going to complain about this solution :)

laenger commented 9 years ago

oh and will you pass in the primitive type (int, array, string, ...) into the transformer or only the raw string? or will users be able to change the header of the transformer function according to what the json is expected to look like? e.g:

[mappingProvider mapFromKey:@"country" toProperty:@"country" forClass:[User class] withTransformer:^(NSArray* a) {
    Country *country = [[Country alloc] initWithX:a[0] andY:a[1]];
    return country;
]};
aryaxt commented 9 years ago

The transformer would take whatever is in the dictionary for the given key, so it could be anything (string, number, array, dictionary, bool)

aryaxt commented 9 years ago

Feature is implemented in a separate branch and docs are updated. Will do more testing and merge into master