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

OCMapper2.1 seems not working in Xcode 5? #46

Closed seaguest closed 8 years ago

seaguest commented 8 years ago

Hello,

I am using OCMapper in my Xcode 5 project which is under OS X 10.8.5.

I am trying the sample test as following, but the user_id is null, the object didn't get mapped I don't know why?

Here is my Model:


#import <Foundation/Foundation.h>

@interface User : NSObject

@property (nonatomic) int user_id;

@property (nonatomic) NSString* registration;

@end

Here is my Test


#import <XCTest/XCTest.h>
#import "ObjectMapper.h"
#import "InCodeMappingProvider.h"
#import "ObjectInstanceProvider.h"
#import "CommonLoggingProvider.h"
#import "User.h"

@interface TestJson : XCTestCase

@property (nonatomic, strong) ObjectMapper *mapper;
@property (nonatomic, strong) InCodeMappingProvider *mappingProvider;

@end

@implementation TestJson
@synthesize mapper;
@synthesize mappingProvider;

- (void)setUp
{
    [super setUp];

    self.mappingProvider = [[InCodeMappingProvider alloc] init];
    self.mapper = [[ObjectMapper alloc] init];
    self.mapper.mappingProvider = self.mappingProvider;
}

- (void)tearDown
{
    self.mapper = nil;
    self.mappingProvider =  nil;
    [super tearDown];
}

- (void)test1
{

    NSMutableDictionary *dic = [[NSMutableDictionary alloc]init];
    [dic setObject:[NSNumber numberWithInt:10] forKey:@"user_id"];
    [dic setObject:@"Value2" forKey:@"registration"];

    User *user = [self.mapper objectFromSource:dic toInstanceOfClass:[User class]];
    NSLog(@" user.user_id - %@", user.user_id);    // here the user.user_id is null
}

@end

So I have 3 questins: 1, is Xcode 5 + OS X 10.8 supported by the latest OCMapper 2.1 version?

2, I tried to use like this (I saw on StackOverflow) User *user = [User objectFromDictionary:dic]; but this needs to add #import "NSObject+ObjectMapper.h"

Is this the right way to use OCMapper, why we need a mapper and mappingProvider?

3, in case the Model has more properties than the dictionary, for exampel, we have only user_id in the dictionary while User has user_id + registration, does OCMapper support the optional mapping?

aryaxt commented 8 years ago

First of all your model has a property of type int, that's not supported, you should use NSNumber for numeric values and booleans similar to CoreData

1- Yes 2- There are 2 ways to use it, either through the NSObject category or using the methods in ObjectMapper class which is a singleton

[[ObjectMapper sharedInstance] objectFromSource:dict toInstanceOfClass:User.class];

3- OCMapper goes through the dictionary keys, and if it finds a matching property then it maps it, otherwise it'll ignore it. So yes it does support optional mapping

seaguest commented 8 years ago

@aryaxt , thanks for your reply. I tried with NSNumber, but it still doesn't work, did I miss something? Or is this due to the version of Xcode or OCMapper?

@interface User : NSObject
@property (nonatomic) NSNumber* user_id;
@property (nonatomic) NSString* registration;
- (NSString *)description;
@end

@implementation User
- (NSString *)description {
    return [NSString stringWithFormat: @"User: user_id=%@ registration=%@", self.user_id, self.registration];
}
@end

- (void)test1
{

    NSMutableDictionary *dic = [[NSMutableDictionary alloc]init];
    [dic setObject:[NSNumber numberWithInt:10] forKey:@"user_id"];
    //[dic setObject:@"11" forKey:@"user_id"];
    [dic setObject:@"my test registration" forKey:@"registration"];

    //User *user = [self.mapper objectFromSource:dic toInstanceOfClass:[User class]];

    User *user = [User objectFromDictionary:dic];

    NSLog(@" dictionary is - %@", dic);
    NSLog(@" ******* user is - %@", user);
}

Now I get:

2016-04-02 10:33:30.504 test[1660:90b]  dictionary is - {
    registration = "my test registration";
    "user_id" = 10;
}
2016-04-02 10:33:30.505 test[1660:90b]  ******* user is - User: user_id=(null) registration=my test registration
aryaxt commented 8 years ago

Your dictionary has a string for user_id, but your property is an NSNumber { "user_id" : 12 } This would map correctly.

But in your case you have a string as dictionary, so you either need to change that or change the property to be a string

seaguest commented 8 years ago

@aryaxt sorry, I used [dic setObject:[NSNumber numberWithInt:10] forKey:@"user_id"];

user_id should be a NSNumber , no? The result for this is

2016-04-02 10:45:39.464 test[1777:90b]  dictionary is - {
    registration = "my test registration";
    "user_id" = 10;
}
2016-04-02 10:45:39.494 test[1777:90b]  ******* user is - User: user_id=(null) registration=my test registration

If I just add user_id with NSNumber, then I get

2016-04-02 10:52:16.201 test[1825:90b]  dictionary is - {
    "user_id" = 10;
}
2016-04-02 10:52:16.212 test[1825:90b]  ******* user is - User: user_id=(null) registration=(null)

I just tried to add String, and tried the second usage of OCmapper as well, the user_id is always null.

seaguest commented 8 years ago

@aryaxt Through debugging, it said WLog(@"Unable to map from key(%@) to property(%@) for class (%@)", key, propertyName, NSStringFromClass(class));

It seems the OCMapper can;t find properly the property name for user_id in User Model.