Coder Social home page Coder Social logo

aryaxt / ocmapper Goto Github PK

View Code? Open in Web Editor NEW
347.0 20.0 45.0 421 KB

Objective-C library to easily map NSDictionary to model objects, works perfectly with Alamofire. ObjectMapper works similar to GSON

License: MIT License

Ruby 0.22% Objective-C 98.09% Swift 1.69%

ocmapper's Introduction

Data Mapping library for Objective C

Build Status Version

OCMapper is a data mapping library for Objective C that converts NSDictionary to NSObject. My inspiration behind writing OCMapper was to achieve two things:

  • Simplify/Automate Data retrieval through web services
  • Avoid adding parsing logic to model objects (I'm a big fan of separation of responsibilities!!!)

Swift Support

OCMapper takes advantage of the objective c runtime API, and will only work with classes that inherit from NSObject.

** Don't use OCMApper with classes written in swift **

Alamofire Extension

https://github.com/Alamofire/Alamofire

public extension Request {
    
    public func responseObjects<T: NSObject> (type: T.Type, completion: (NSURLRequest, NSURLResponse?, [T]?, NSError?)->()) -> Self {
        
        return response(serializer: Request.JSONResponseSerializer(options: .AllowFragments)) { request, response, json, error in
            
            if let error = error {
                completion(request, response, nil, error)
            }
            else {
                let objects = ObjectMapper.sharedInstance().objectFromSource(json, toInstanceOfClass: type) as? [T]
                completion(request, response, objects, nil)
            }
        }
    }
    
    public func responseObject<T: NSObject> (type: T.Type, completion: (NSURLRequest, NSURLResponse?, T?, NSError?)->()) -> Self {
        
        return response(serializer: Request.JSONResponseSerializer(options: .AllowFragments)) { request, response, json, error in
            
            if let error = error {
                completion(request, response, nil, error)
            }
            else {
                let object = ObjectMapper.sharedInstance().objectFromSource(json, toInstanceOfClass: type) as? T
                completion(request, response, object, nil)
            }
        }
    }
    
}

Extension Usage

let request = Manager.sharedInstance.request(requestWithPath("example.com/users", method: .GET, parameters: nil))
        
request.responseObjects(User.self) { request, response, users, error in
    // users is an array of User objects
}


let request = Manager.sharedInstance.request(requestWithPath("example.com/users/5", method: .GET, parameters: nil))
        
request.responseObject(User.self) { request, response, user, error in
    // user is an instance of User
}

Features:

  • Supports array mapping
  • Supports tree structure mapping
  • Auto maps everything based on key/values
  • You can write mapping for non-matching dictionary/property keys
  • Override portion of mapping using transformers
  • Supports Core Data (NSManagedObjects mapping)
  • Does not require subclassing or adding any extra code to your models
  • Auto date conversion, and configurable DateFormatters
  • Auto underscore to camel case mapping

Examples

@interface User
@property (nonatomic, strong) NSString *firstName;
@property (nonatomic, strong) NSString *lastName;
@property (nonatomic, strong) NSNumber *age;
@property (nonatomic, strong) NSDate *dateOfBirth;
@property (nonatomic, strong) NSDate *accountCreationDate;
@property (nonatomic, strong) Address *address;
@property (nonatomic, strong) NSMutableArray *posts;
@end

@interface Address
@property (nonatomic, strong) NSString *city;
@property (nonatomic, strong) NSString *country;
@end

@interface Post
@property (nonatomic, strong) NSString *title;
@property (nonatomic, strong) User *author;
@property (nonatomic, strong) NSDate *datePosted;
@end

Simple Automatic Mapping

{
   "firstName"   : "Aryan",
   "lastName"    : "Ghassemi",
   "age"         : 26,
   "dateOfBirth" : "01/01/2013"
}

User *user = [User objectFromDictionary:aDictionary];

Nested Automatic Mapping

In this case everything is mapped automaticly because all key/values are similar. "address" will automatically convert to "Address" Object. "posts" will automatically convert to an array of "Post" objects. The library detect the plural nouns, and finds the right class to be used for mapping

{
   "firstName"   : "Aryan",
   "lastName"    : "Ghassemi",
   "age"         : 26,
   "dateOfBirth" : "01/01/2013",
   "address"     : { 
                        "city" : "San Diego", 
                        "country" : "US"  
                   },
   "posts"       : [
                         {
                             "title" : "Post 1 title",
                             "datePosted : "04/15/2013",
                         },
                         {
                             "title" : "Post 2 title",
                             "datePosted : "04/12/2013",
                         }
                   ]
}

User *user = [User objectFromDictionary:aDictionary];

Complex Mapping

Here is a more complex scenario where the dictionary keys do not match the model property names. The key for date of birth changes from "dateOfBirth" to "dob", and the key for "author" is named "from"

{
   "firstName"   : "Aryan",
   "lastName"    : "Ghassemi",
   "age"         : 26,
   "dob" : "01/01/2013",
   "address"     : { 
                        "city" : "San Diego", 
                        "country" : "US"  
                   },
   "posts"       : [
                         {
                             "title" : "Post 1 title",
                             "datePosted : "04/15/2013",
                             "from" : { 
                                             "firstName" : "Chuck", 
                                             "lastName" : "Norris" 
                                        }
                         },
                         {
                             "title" : "Post 2 title",
                             "datePosted : "04/12/2013",
                             "form" : { 
                                             "firstName" : "Chuck", 
                                             "lastName" : "Norris" 
                                        }
                         }
                   ]
}

// Handle different key for dateOfBirth
[inCodeMappingProvider mapFromDictionaryKey:@"dob" toPropertyKey:@"dateOfBirth" forClass:[User class]];

// Handle mapping of "form" to "auther" object
// Mapping would NOT be required if dictionary key and property were both named the same
[inCodeMappingProvider mapFromDictionaryKey:@"from" toPropertyKey:@"author" withObjectType:[User class] forClass:[Comment class]];

User *user = [User objectFromDictionary:aDictionary];

Mapping Array on root level

[
   {
      "firstName" : "Aryan",
      ... rest of JSON data ...
   },
   {
      "firstName" : "Chuck",
      ... rest of JSON data ...
   },
]

NSArray *users = [User objectFromDictionary:aDictionary];

Flat Data to Complex Object

This is no longer enabled on default in order to improve performance. There is a property named normalizeDictionary in ObjectMapper class that allows you to turn this feature on if needed.

{
      "firstName"           : "Aryan",
      "city"                : "San Diego"
      "country"             : "United States"
}

   // We map city and country to a nested object called 'address' inside the 'user' object
	[self.mappingProvider mapFromDictionaryKey:@"city" toPropertyKey:@"address.city" forClass:[User class]];
	[self.mappingProvider mapFromDictionaryKey:@"country" toPropertyKey:@"address.country" forClass:[User class]];
	
	User *user = [User objectFromDictionary:aDictionary];
      NSLog(@"FirstName:%@   City:%@  Country:%@", 
      user.firstName,
      user.address.city, 
      user.address.coutnry);

Date Conversion

Automapper has a property named defaultDateFormatter, and when the property is set it'll use this NSDateFormatter for date conversions on all NSDate properties. It's recomended to set the defaultDateFormatter for best performance. Note that custom dateFormatters have priority over defaultDateFormatter

[inCodeMappingProvider setDefaultDateFormatter:aDefaultDateFormatter];

ObjectMapper uses a list of common NSDateFormatters to convert string to NSDate. Here is a list of common dateFormats supported out of the box

"yyyy-MM-dd"
"MM/dd/yyyy"
"yyyy-MM-dd'T'HH:mm:ss.SSSSSSSZ"
"yyyy-MM-dd HH:mm:ss"
"MM/dd/yyyy HH:mm:ss aaa"
"yyyy-MM-dd'T'HH:mm:ss'Z'"

You can also have custom NSDateFormatter specific to classes & properties

NOTE: Setting DateFormatter is not required as long as all date formats are standard or if the defaultDateFormatter knows how to parse the dates. The code below is just to demonstrate that it's possible to set custom dateformatters but it is not required due to use of standard date formats in this example.

{
      "firstName"           : "Aryan",
      "accountCreationDate" : "01/21/2005"
      "dateOfBirth"         : "2005-21-01"
}

// Custom formatter for account creation date
NSDateFormatter *accountCreationFormatter = [[NSDateFormatter alloc] init];
[accountCreationFormatter setDateFormat:@"MM/dd/yyyy"];
[inCodeMappingProvider setDateFormatter:accountCreationFormatter forProperty:@"accountCreationDate" andClass:[User class]];

// Custom formatter for date of birth
NSDateFormatter *dateOfBirthFormatter = [[NSDateFormatter alloc] init];
[dateOfBirthFormatter setDateFormat:@"yyyy-dd-MM"];
[inCodeMappingProvider setDateFormatter:dateOfBirthFormatter forProperty:@"dateOfBirth" andClass:[User class]];

User *user = [User objectFromDictionary:aDictionary];

Data Transformers

Data transformers allow you to capture a certain part of mapping and manually map it. It alsso opens room for polymorphic mapping.

Transform a field to another

{
   "firstName" : "Aryan",
   "country" : "United States"
}

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

[mappingProvider mapFromDictionaryKey:@"country" toPropertyKey:@"country" forClass:[User class] withTransformer:^id(id currentNode, id parentNode) {
    return [[Country alloc] initWithName:currentNode];
}];

Using transformer for polymorphic relationships

{
   "firstName" : "Aryan",
   "vehicleType" : "car",
   "vehicle" : { /*specific product Info*/ },
}

@implementation User
@property(nonatomic, strong) NSString *firstName;
@property(nonatomic, strong) Vehicle *vehicle;
@end

[mappingProvider mapFromDictionaryKey:@"vehicle" toPropertyKey:@"vehicle" forClass:[User class] withTransformer:^id(id currentNode, id parentNode) {
    NSString *productType = [parentNode objectForKey:@"vehicleType"];
    Vehicle *vehicle;
    
    if ([productType isEqual:@"car"])
    {
    	vehicle = [Car objectFromDictionary:currentNode];
    }
    else if ([productType isEqual:@"bike"])
    {
    	vehicle = [Bike objectFromDictionary:currentNode];
    }
    
    
    return vehicle;
}];

// Or event better

[mappingProvider mapFromDictionaryKey:@"vehicle" toPropertyKey:@"vehicle" forClass:[User class] withTransformer:^id(id currentNode, id parentNode) {

    NSString *productType = [parentNode objectForKey:@"vehicleType"];
    Class class = NSClassFromString(productType.capitalizedString);
    return [class objectFromDictionary:currentNode];
}];

Other posibilities with the transformer

{
   "firstName" : "Aryan",
   "image" : "BASE64_ENCODED_STRING"
}

@implementation User
@property(nonatomic, strong) NSString *firstName;
@property(nonatomic, strong) UIImage *image;
@end

[mappingProvider mapFromDictionaryKey:@"image" toPropertyKey:@"image" forClass:[User class] withTransformer:^id(id currentNode, id parentNode) {

    return [UIImage imageFromBase64String:currentNode];
}];

Inverse mapping

Inverse mapping referrs to mapping of an object to a dictionary. This is very similar to a standard dictionary to property mapping. The following methods can be used in order to setup custom mapping for object to dictionary mapping.

- (void)mapFromPropertyKey:(NSString *)propertyKey toDictionaryKey:(NSString *)dictionaryKey forClass:(Class)class;
- (void)mapFromPropertyKey:(NSString *)propertyKey toDictionaryKey:(NSString *)dictionaryKey forClass:(Class)class withTransformer:(MappingTransformer)transformer;
- (void)setDateFormatter:(NSDateFormatter *)dateFormatter forDictionary:(NSString *)property andClass:(Class)class;

InCodeMappingProvider class has a property named automaticallyGenerateInverseMapping. This property is set to true on default, which means whenever a dictionary-to-property mapping is set, an inverse-mapping is automatically generated, and therefore there is no need to manually write mapping for object-to-dictionary mapping. The only exception is that mapping dictionary-to-property with data-transformers cannot be automatically inversed.

Date formatters are also created for an inverse relationship when automaticallyGenerateInverseMapping is set to true.

Core Data Support

In order to use core data you can add a ManagedObjectInstanceProvider to ObjectMapper

ManagedObjectInstanceProvider *instanceProvider = [[ManagedObjectInstanceProvider alloc] initWithManagedObjectContext:moc];
	
[[ObjectMapper sharedInstance] addInstanceProvider:instanceProvider];

On default Object mapper creates a new instance of NSManagedObject on every mapping. In order to update an existing record you could provide unique keys for a given class and ObjectMapper would automatically update the existing record.

[managedObjectInstanceProvider setUniqueKeys:@[@"userId"] forClass:[User class] withUpsertMode:UpsertModePurgeExistingObject];

When assigning keys for classes OCMApper also requires an enum describes how ObjectMapper should upsert existing records.

  • UpsertModeUpdateExistingObject: This option creates a new temporary instance of managed object, and then based on the given keys it attempts to find an existing record. If it finds ONE record it updates all properties of the existing managed object and finally removes the temporary object. When using this upsert mode, delete does not get called on any of the related managed objects, and therefore records remain in memory. For instance if the user's address has changed from A to B address would be updated properly, but both records would remain in core data.

  • UpsertModePurgeExistingObject: This option creates a new instance of managed object, and then based on the given keys it attempts to find an existing record. If it finds ONE record it calls delete on that record, and then inserts the newly created object into context. Using this upser mode, delete gets called on existing managed object, and therefore core data would delete all related relational objects, and all "delete rules" in core data model would be applied. For instance, if a user get's updated, and phone number changes from A to B, and if trhe delete rule is marked as cascade, then Address A would be removed and address B would be assigned to the user.

Different Usage & Helpers

// Using ObjectMapper Directly
ObjectMapper *mapper = [[ObjectMapper alloc] init];
Urse *user = [mapper objectFromSource:dictionary toInstanceOfClass:[User class]];

// Using ObjectMapper Singleton Instance
Urse *user = [[ObjectMapper sharedInstance] objectFromSource:dictionary toInstanceOfClass:[User class]];

In order to use these categories you must add your mapping provider to the singleton Instance

// Using NSObject Category
User *user = [User objectFromDictionary:aDictionary];

// Using NSDictionary Category
User *user = [aDictionary objectForClass:[User class]];

Change Log

2.1

Allow automatic conversion of underscore keys to camelCase properties

  • first_name to firstName as String
  • email_confirmation to emailConfirmation as EmailConfirmation class
  • email_confirmations to emailConfirmations as NSArray of EmailConfirmation class

2.0

Fixed a bug that was instroduced in 1.8 where classes with two words in they weren't getting mapped automatically. EX (sessionUser would try to map to Sessionuser class instead of SessionUser and would fail to map)

1.9

Automatic NSString to NSNumber and NSNumber to NSString conversion

1.8

  • No longer loading bundle class names in memory on init
  • Fixed for #22
  • No longer need to write mapping for non-array pointers as long as key/property names match (ex: "location" key would automatically map to "location" property event if the class type is named "Address" )
  • Wrote tests for mapping swift classes

Note:

Automatic mapping treats nested array differently. ObjectMapper capitalizes the first character of the dictionary key before checking for a conversion class.

  • "UserAddress" will automatically be mapped to "UserAddress"
  • "userAddress" will automatically be mapped to "UserAddress"
  • "useraddress" will NOT be mapped to "UserAddress", you need to manually write mapping

ocmapper's People

Contributors

aryaxt avatar jeroentrappers avatar lutherbaker avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ocmapper's Issues

custom class for parsing NSArray

Dears,
Suppose I have the objects below:

@interface Author : NSObject
@property(nonatomic, strong) NSMutableArray *posts;
@end

@interface Post : NSObject
@property(nonatomic, strong) NSString *title;
@end

@interface AnotherPost : NSObject
@property(nonatomic, strong) NSString *title;
@end

And the dictionary data like:

{
    "posts": [
        {
            "title": "title 1"
        },
        {
            "title": "title 2"
        }
    ]
}

The statement below will deserialize Author object using Post class for parsing the array data.

Author *author = [Author objectFromDictionary:aDictionary];

My question is how can I configure AnotherPost class for parsing the array data instead of Post class?

It would be appreciate for you to give me some guides.

Thank you:)

Alamofire extension for Alamofire 4.x

Hi!
I use OCMapper with Alamofire in my application (I would think it is quite a common use case), so like in my previous issue (#53), I would appreciate to see an Alamofire extension example in the README. I already updated my app to Swift 3 and thus Alamofire 4.x, and created the extension myself, so I would be happy to create a pull request to update the readme with both examples (for Alamofire 3.x and 4.x). Do you accept pull requests like this?

I will post my solution here soon for anyone to check.

MissingMappingProvider is Swift usage

Hello,

could you help me, when I try to run the following command

ObjectMapper.sharedInstance().objectFromSource(self.data, toInstanceOfClass: Message.self) as? Message 

it returns the following error:

2015-03-12 11:31:16.385 websocket[41545:3347379] *** Terminating app due to uncaught exception 'MissingMappingProvider', reason: 'Mapping provider is not set'

I'm forgetting to do something?

Swift 3 compatibility

Hey, I'd love to see this lib available in Swift 3 so I can implement it in my project.

Thanks ๐Ÿ˜„

Not Working in Swift 2.0

Hi I'm using OCMapper in swift 1.2 and it is working correctly. But migrating to swift 2.0, it gives nil object.

In My Object

public class Response: NSObject {

    var flag = false
    var message : String?
    var announcement : String?
    var data : User?
}

public class User : Object  {

    dynamic var id = ""
    dynamic var imgName = ""
    dynamic var imageUrl = ""
    dynamic var mobile = ""
    dynamic var firstName = ""
    dynamic var lastName = ""
    dynamic var email = ""
}

User is a Realm Object. When I map object from dictionary

 let response = dictionary?.toClass(Response.self)

or

let user = ObjectMapper.sharedInstance().objectFromSource(dictionary, toInstanceOfClass: Response.self) as? Response

Response gives data = nil and mapping failed.
It is working in Swift 1.2 so any issue of OCMapper with Swift 2.0 or any update for it?

Is OCMapper thread-safe?

Hi,

I've been using OCMapper for several weeks now and I'm a big fan! While there's a few things I'd love to see improved - in general it was the best JSON <-> Object library I could find for iOS.

However, every once and a while I noticed my app is crashing and the stack trace points inside of OCMapper. It's very difficult to reproduce which makes the crash even worse in my mind.

But, my theory is that OCMapper isn't thread-safe. We have a thread pool handling responses from the server and OCMapper processes everything as a singleton.

Is this a known limitation? I can handle the results in a single thread to be safe as well but wanted to know if it's supposed to be thread-safe and the issue is elsewhere in my code.

@interface ObjectMapper()
@property (nonatomic, strong) NSMutableArray *commonDateFormaters;
@property (nonatomic, strong) NSMutableDictionary *mappedClassNames;
@property (nonatomic, strong) NSMutableDictionary *mappedPropertyNames;
@property (nonatomic, strong) NSMutableArray *instanceProviders;
@end

Automatically convert between camelCase and underscores (the other way around)

You added automatic conversion from underscores to camelCase in 2.1 (#31), but it doesn't seem to work the other way: converting camelCase to underscores. This way it is not possible to communicate with a server using underscores correctly without creating separate modell classes for incomming and outgoing communication.

Or am I doing something wrong? I am using it from Swift if it matters.

Support for OS X platform?

I was hoping to use this for an OS X / Swift project, but noticed that it only supports iOS. Is this something that you're considering adding? If you could point me in the right direction, maybe I could try getting it to work.

processDictionaryFromObject doesn't work in unit test target

Because the current bundle is not the main bundle, but it's the unit test bundle.
Try using runtime api instead

- (id)processDictionaryFromObject:(NSObject *)object {

if ([NSBundle mainBundle] != [NSBundle bundleForClass:object.class] && [object class] != [NSArray class])
    {
        return object;
    }

Usage

I have an array and need to a need to map the indexpath.row dictionary to my preconfigured nsobject .
Which files should I import to my project (from the ocmapper library)?
Which the recommended method to configure the mapping?
User *user = [User objectFromDictionary:aDictionary];?

[[ObjectMapper sharedInstance] dictionaryFromObject:object] doesn't work if the object comes from a framework

I know that MESRecipePreviewRecipeIngredientViewModel can be converted into a dictionary normally in a standard iOS app project. The moment I moved it to another private pod framework, I saw this error:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Invalid type in JSON write (MESRecipePreviewRecipeIngredientViewModel)'
*** First throw call stack:
(
    0   CoreFoundation                      0x0000000103ccac65 __exceptionPreprocess + 165
    1   libobjc.A.dylib                     0x0000000103963bb7 objc_exception_throw + 45
    2   CoreFoundation                      0x0000000103ccab9d +[NSException raise:format:] + 205
    3   Foundation                          0x00000001035fafd0 _writeJSONValue + 689
    4   Foundation                          0x00000001035ff34d ___writeJSONArray_block_invoke + 130
    5   CoreFoundation                      0x0000000103c14026 __53-[__NSArrayI enumerateObjectsWithOptions:usingBlock:]_block_invoke + 70
    6   CoreFoundation                      0x0000000103c13f5c -[__NSArrayI enumerateObjectsWithOptions:usingBlock:] + 284
    7   Foundation                          0x00000001035ff262 _writeJSONArray + 264
    8   Foundation                          0x00000001035faf3c _writeJSONValue + 541
    9   Foundation                          0x00000001035ff46f ___writeJSONObject_block_invoke + 220
    10  CoreFoundation                      0x0000000103c3ecd5 __65-[__NSDictionaryI enumerateKeysAndObjectsWithOptions:usingBlock:]_block_invoke + 85
    11  CoreFoundation                      0x0000000103c3ebec -[__NSDictionaryI enumerateKeysAndObjectsWithOptions:usingBlock:] + 236
    12  Foundation                          0x00000001035ff080 _writeJSONObject + 376
    13  Foundation                          0x00000001035faea6 _writeJSONValue + 391
    14  Foundation                          0x00000001035ff46f ___writeJSONObject_block_invoke + 220
    15  CoreFoundation                      0x0000000103c3ecd5 __65-[__NSDictionaryI enumerateKeysAndObjectsWithOptions:usingBlock:]_block_invoke + 85
    16  CoreFoundation                      0x0000000103c3ebec -[__NSDictionaryI enumerateKeysAndObjectsWithOptions:usingBlock:] + 236
    17  Foundation                          0x00000001035ff080 _writeJSONObject + 376
    18  Foundation                          0x00000001035faea6 _writeJSONValue + 391
    19  Foundation                          0x00000001035ff46f ___writeJSONObject_block_invoke + 220
    20  CoreFoundation                      0x0000000103c3ecd5 __65-[__NSDictionaryI enumerateKeysAndObjectsWithOptions:usingBlock:]_block_invoke + 85
    21  CoreFoundation                      0x0000000103c3ebec -[__NSDictionaryI enumerateKeysAndObjectsWithOptions:usingBlock:] + 236
    22  Foundation                          0x00000001035ff080 _writeJSONObject + 376
    23  Foundation                          0x00000001035faea6 _writeJSONValue + 391
    24  Foundation                          0x00000001035ff34d ___writeJSONArray_block_invoke + 130
    25  CoreFoundation                      0x0000000103c14026 __53-[__NSArrayI enumerateObjectsWithOptions:usingBlock:]_block_invoke + 70
    26  CoreFoundation                      0x0000000103c13f5c -[__NSArrayI enumerateObjectsWithOptions:usingBlock:] + 284
    27  Foundation                          0x00000001035ff262 _writeJSONArray + 264
    28  Foundation                          0x00000001035faf3c _writeJSONValue + 541
    29  Foundation                          0x00000001035ff34d ___writeJSONArray_block_invoke + 130
    30  CoreFoundation                      0x0000000103c14026 __53-[__NSArrayI enumerateObjectsWithOptions:usingBlock:]_block_invoke + 70
    31  CoreFoundation                      0x0000000103c13f5c -[__NSArrayI enumerateObjectsWithOptions:usingBlock:] + 284
    32  Foundation                          0x00000001035ff262 _writeJSONArray + 264
    33  Foundation                          0x00000001035faf3c _writeJSONValue + 541
    34  Foundation                          0x00000001035ff46f ___writeJSONObject_block_invoke + 220
    35  CoreFoundation                      0x0000000103c3ecd5 __65-[__NSDictionaryI enumerateKeysAndObjectsWithOptions:usingBlock:]_block_invoke + 85
    36  CoreFoundation                      0x0000000103c3ebec -[__NSDictionaryI enumerateKeysAndObjectsWithOptions:usingBlock:] + 236
    37  Foundation                          0x00000001035ff080 _writeJSONObject + 376
    38  Foundation                          0x00000001035faea6 _writeJSONValue + 391
    39  Foundation                          0x00000001035ff34d ___writeJSONArray_block_invoke + 130
    40  CoreFoundation                      0x0000000103c14026 __53-[__NSArrayI enumerateObjectsWithOptions:usingBlock:]_block_invoke + 70
    41  CoreFoundation                      0x0000000103c13f5c -[__NSArrayI enumerateObjectsWithOptions:usingBlock:] + 284
    42  Foundation                          0x00000001035ff262 _writeJSONArray + 264
    43  Foundation                          0x00000001035faf3c _writeJSONValue + 541
    44  Foundation                          0x00000001035facea -[_NSJSONWriter dataWithRootObject:options:error:] + 137
    45  Foundation                          0x00000001035fd76b +[NSJSONSerialization dataWithJSONObject:options:error:] + 345
    46  React                               0x0000000101d2b2ee RCTJSONStringify + 94
    47  React                               0x0000000101c99152 __70-[RCTContextExecutor executeJSCall:method

I.e. I was trying to use OCMapper to convert my ViewModel class into a dictionary that React Native can consume. RN is barfing because the object didn't get converted at all

OCMapper2.1 seems not working in Xcode 5?

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?

Bad data could cause crash

- (NSString *)propertyNameForObject:(NSObject *)object byCaseInsensitivePropertyName:(NSString *)caseInsensitivePropertyName
{
    NSString *result = nil;
    Class currentClass = [object class];
    NSString *key = [NSString stringWithFormat:@"%@.%@", NSStringFromClass(currentClass), caseInsensitivePropertyName];

    if (self.propertyNameDictionary[key])
        return self.propertyNameDictionary[key];

    while (currentClass && currentClass != [NSObject class])
    {
        unsigned int outCount, i;
        objc_property_t *properties = class_copyPropertyList(currentClass, &outCount);

        for (i = 0; i < outCount; i++)
        {
            objc_property_t property = properties[i];
            NSString *propertyName = [NSString stringWithUTF8String:property_getName(property)];

            if ([[propertyName lowercaseString] isEqual:[caseInsensitivePropertyName lowercaseString]])
            {
                result = propertyName;
                break;
            }
        }

        free(properties);

        if (result)
        {
            self.propertyNameDictionary[key] = result;
            return result;
        }

        currentClass = class_getSuperclass(currentClass);
    }

    return nil;
}

Do a null check on properties before calling free
Also do a null check for key?

Array of dates

I need array on NSDate, like this

@objc public class User: NSObject {
var dates: [NSDate]?
}

And in JSON
{
"dates": [
"11/12/13",
]
}

But providing property does not work.

let propertyProvider = InCodeMappingProvider()
propertyProvider.mapFromDictionaryKey("dates", toPropertyKey: "dates", withObjectType: NSDate.self, forClass: User.self)

ObjectMapper still generates strings.

Should I use provider with transformer or there is other way to do what i want?

Works fine if I add to method

  • (id)objectFromSource:(id)source toInstanceOfClass:(Class)class;

condition

else if ([source isKindOfClass:[NSString class]] && class == [NSDate class] ){
return [self dateFromString:source forProperty:nil andClass:NULL];
}

But it looks ugly)

Automatically convert between underscores and camelCase

I often have to interact with APIs that use underscores in their JSON responses (e.g. 'some_property'). This forces me to do a lot of manual mapping to convert to ObjC/Swift camel case properties (e.g. 'someProperty). It would be fantastic if OCMapper could automatically convert between the two.

Swift Generic in OCMapper

Hi, i want to use generic in class. But i dun know how to get it.

let provider = InCodeMappingProvider()
provider.mapFromDictionaryKey("data", toPropertyKey: "data", withObjectType: BrandSimpleWebModel.self, forClass: PaginationListModel<BrandSimpleWebModel>.self) 
ObjectMapper.sharedInstance().mappingProvider = provider                
let paginationListModel = ObjectMapper.sharedInstance().objectFromSource(response, toInstanceOfClass: PaginationListModel<BrandSimpleWebModel>.self) as! PaginationListModel<BrandSimpleWebModel>
class PaginationListModel<T>: NSObject{
var totalPage: NSNumber!
var totalItem: NSNumber!
var currentPage: NSNumber!
var itemPerPage: NSNumber!
var data: [T]!

When i print "data", the result is nil. If i replace var data:[T]! to var data:[BrandSimpleWebModel]! then i can get the data. Please help me. Thank you

watchOS support

Is there a way to use OCMapper with watchOS? If not at the moment are there any chances to support watchOS platform any soon?

I'm integrating watch support in my project and already using OCMapper in the iOS app. I thought to pass my objects as json between host app and watch and to automatically serialize/deserialize them but I've stuck integrating OCMapper to watch extension and getting the following error while executing pod install:

Analyzing dependencies
[!] The platform of the target Watch Extension (watchOS 3.1) is not compatible with OCMapper (2.1), which does not support watchos.

the podfile:

target 'Watch Extension' do
pod 'OCMapper'
end

Support for custom factory methods

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]);
    }
}

Nested mapping of classes

I have json which contains an array of other classes as well so how to do nested mapping between classes.
Example
@interface APIOrganization : NSObject

@Property (nonatomic , strong) NSString *id;
@Property (nonatomic , strong) NSString *name;
@Property (nonatomic , strong) APIPhoto *rmcPhoto;
@Property (nonatomic , strong) NSMutableArray *Service;
@Property (nonatomic , strong) NSMutableArray *osd;
@EnD

Here the APIOrganization class i am using

APIOrganization *ApiOrg = [[ObjectMapper sharedInstance] objectFromSource:orgDict toInstanceOfClass:[APIOrganization class]];
Service is array of class Service class
but i am not getting the array which contain Service

Please guide me its very urgent
@interface APIService : NSObject
@Property (nonatomic , strong) NSString *id;// Doubt

@Property (nonatomic , strong) NSString *name;

@Property (nonatomic , strong) NSString *descriptions;

@Property (nonatomic , strong) NSString *updatedOn;

Not mapping dictionary

Hello!
Maybe its bug, i wanna report it.

So, we have Class:

@interface TFResponse : NSObject
@property(nonatomic, assign) BOOL status;
@property(nonatomic, weak) NSDictionary *data;
@end

And DICT:

{
    data =     {
        code = 0;
        message = "test message";
    };
    status = 0;
}

After use code:

TFResponse *response = [TFResponse objectFromDictionary:responseObject];
                   NSLog(@"API: TFResponse status: %d", response.status);
                   NSLog(@"API: TFResponse data: %@", response.data);
//                   response.data = responseObject[@"data"];

We have result:

API: TFResponse status: 0
API: TFResponse data: {
}

For fix that, i use:

response.data = responseObject[@"data"];

But maybe it is a bug, and so I decided to report it.

Wait answer.
Best regards,
Ivan.

Use same ObjectMapper for NSObject & NSManagedObject

Get rid of instanceProvider property, and instead have an array that holds objects of type @protocol(InstanceProvider).

Implement chain of responsibilities so that the object mapper decides which instanceProvider to use depending on whether class inherits from NSManagedObject or not.

NSDate Default Mapping

My understanding from the documentation of OCMapper is that if nothing is set, it should automatically map and reverse map an NSDate. But unfortunately, it doesn't. When it is mapping from object to dictionary, it uses the "description" property of NSDate to get the string. But when it converts from dictionary to object, it is unable to convert it back to NSDate, as it doesn't have a matching dateFormatter. The workaround is to set the defaultDateFormatter to a dateFormatter independent of the locale of the device.

Crash with : class is not key value coding-compliant for the key(s): -hash or -debugDescription or -description

I use an instance of ObjectMapper and then configure it by adding an InCodeMappingProvider as the mappingProvider. For example :

self.mapper_ = [[ObjectMapper alloc] init];
InCodeMappingProvider *inCodeProvider = [[InCodeMappingProvider alloc] init];
[self.mapper setMappingProvider:inCodeProvider];

I have a user object like this :

@interface SSUserStats : SSObject <SSObjectMapping>

@property (nonatomic, strong, nullable) NSNumber * storeCount;
@property (nonatomic, strong, nullable) NSNumber * followerCount;
@property (nonatomic, strong, nullable) NSNumber * followeeCount;

@end

@interface SSUser : NSObject <ObjectMapping>

@property (nonatomic, strong, nullable) NSString  *userId;
@property (nonatomic, strong, nullable) NSString  *email;
@property (nonatomic, strong, nullable) NSString  *username;
@property (nonatomic, strong, nullable) NSString  *firstName;

@property (nonatomic, strong, nullable) UserStats *stats;

@property (nonatomic, strong, nullable) NSString  *profileImageFilename;
@property (nonatomic, strong, nullable) NSString  *headerImageFilename;

@end

When then I try to create a dictionary from a user object and then convert back this dictionary to an object my app crash :

SSUserStats *stats = [[SSUserStats alloc] init];
stats.storeCount = @(42);
stats.followeeCount = @(12);
stats.followerCount = @(21);

SSUser  *user = [[SSUser alloc] init];
user.firstName = @"Adrien";
user.email = @"[email protected]";
user.username = @"flop";
user.stats = stats;

NSDictionary *dict = [self.mapper dictionaryFromObject:user];
NSLog(@"Dic : %@", dict);
User *user2 = [self.mapper objectFromSource:dict toInstanceOfClass:[User class]];
NSLog(@"User2 : %@", [user2 description]);

First log shows :

Dic : {
    debugDescription = "<User: 0x7fa183e0cd20>";
    description = "<User: 0x7fa183e0cd20>";
    firstName = Adrien;
    email = @"[email protected]";;
    hash = 140331679010080;
    stats =     {
        debugDescription = "<UserStats: 0x7fa183e2dde0>";
        description = "<UserStats: 0x7fa183e2dde0>";
        followeeCount = 12;
        followerCount = 21;
        hash = 140331679145440;
        storeCount = 42;
        superclass =         {
        };
    };
    superclass = NSObject;
}

At the third line, my program crash with :

*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<User 0x7fa183f22360> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key hash.'

I'm using Xcode 7, iOS 9. It's really sad because I really like this lib and the way it's architectured. My question is why : hash / superclass / debugDescription / description are processed which leads to this crash, Any idea of how I can fix this. Many thanks.

Property name mapping doesn't support underscore at the middle of the property name?

Hello,

I just found a problem of property name mapping when we have underscore at the middle of the property.

This is linked to
#46

My Model is:

@interface User : NSObject
@property (nonatomic) int user_id;
@property (nonatomic) NSString* registration;
@end

The dictionary is:

{
    registration = "my test registration";
    "user_id" = 10;
}

However OCMapper mapped user_id to userid(without underscore), I guess this is not supposed to be, you may want to map userid to _userid but forgetting the case when we have underscore at the middle.

Ok, I see the code in

    @implementation ObjectInstanceProvider

    // Support underscore case (EX: map first_name to firstName)
    caseInsensitivePropertyName = [caseInsensitivePropertyName stringByReplacingOccurrencesOfString:@"_" withString:@""];

I just saw that automatic underscore mapping from the latest changelog, but what if we want to keep the same name as in he dictionary?

Nested JSON

Hi, i have a JSON like this

{
  "total_item": 250,
  "item_per_page": 50,
  "current_page": 1,
  "total_page": 5,
  "data": [
    {
      "data": {
        "id": 1,
        "name": "Happy New Year 2016",
        "logo": {
          "ratio": 1,
          "path_1x": "https://3.bp.blogspot.com/-KUivQF0u7ME/VoMhw9LmM4I/AAAAAAAAASM/wt4gB6bT-Mk/s640/happy-new-year-2016-wishes.jpg",
          "path_2x": "https://3.bp.blogspot.com/-KUivQF0u7ME/VoMhw9LmM4I/AAAAAAAAASM/wt4gB6bT-Mk/s640/happy-new-year-2016-wishes.jpg"
        },
        "main_category": {
          "id": 0,
          "name": "Mall"
        }
      },
      "type": 2
    },

Inside "data" got another "data". My model class is

    var totalPage: NSNumber!
    var totalItem: NSNumber!
    var currentPage: NSNumber!
    var itemPerPage: NSNumber!
    var data: [T]!

What i going to do is i need to get the data.data from JSON and map to data.
So i write a code

class func createFromJSON<T>(type: T, dictionary:Dictionary<String, AnyObject>, provider: InCodeMappingProvider) -> PaginateListModel<T>
    {
        var model = PaginateListModel<T>()
        model = ObjectMapper.sharedInstance().objectFromSource(dictionary, toInstanceOfClass: PaginateListModel<T>.self) as! PaginateListModel<T>

        let dictData = dictionary["data"] as! [Dictionary<String, AnyObject>]
        provider.mapFromDictionaryKey("data.data", toPropertyKey: "data", withObjectType:  T.self , forClass: PaginateListModel<T>.self)
        ObjectMapper.sharedInstance().mappingProvider = provider
        model.data = ObjectMapper.sharedInstance().objectFromSource(dictData, toInstanceOfClass: T.self) as! [T]


        return model
    }

But i can't get the result. Please help. Thank you.

Automatically parse 0 or 1 to Bool

It is quite common for a server to return 0 or 1 for boolean values. It would be great if OCMapper could automatically parse this as booleans. I use it in Swift but I think this is possible to implement both in Swift and Objective-C.

For now, I created a MappingTransformer for this which I have to set for every parameter where I would like to use it:

Swift 2.x:

let intToBoolTransformer: MappingTransformer = {
    currentNode, parentNode in
    return currentNode as? NSNumber == 1 ? true : false
}

Swift 3.x (Somehow casting to Int always results in nil):

let intToBoolTransformer: MappingTransformer = {
    currentNode, parentNode in
    return currentNode as? NSNumber == 1 ? true : false
}

Thanks in advance!

Crash String - stringByRemovingPercentEncoding

For some weird reason, converting an object to a dictionary crashed with the following error:

valueForUndefinedKey:]: this class is not key value coding-compliant for the key stringByRemovingPercentEncoding

if there was a string generated with the following code set to a property in the object

func generateRandomKey(amountOfCharacters: Int) -> String {

    var alphabet = Array("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXZY0123456789".characters)
    var randomKey = String()

    for (var i = 0; i < amountOfCharacters; i++) {
        randomKey.append(alphabet[Int(arc4random_uniform(62))])
    }

    return randomKey
}

I have now changed to the following solution and it works, funny though:

func generateRandomKey (len : Int) -> String {

    let letters : NSString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

    let randomString : NSMutableString = NSMutableString(capacity: len)

    for (var i=0; i < len; i++){
        let length = UInt32 (letters.length)
        let rand = arc4random_uniform(length)
        randomString.appendFormat("%C", letters.characterAtIndex(Int(rand)))
    }

    return randomString as String
}

How to handle boolean properties?

I have an object with a boolean property but it never gets set, it's always nil. How should I declare this property?

MyObject {
  var id: NSNumber?
  var userId: NSNumber?
  var state: String?
  var active: Bool?
}

ObjectMapper init crashes when running on background thread

When ObjectMapper is initialized in a background thread using GCD (i.e. dispatch_async), an EXC_BAD_ACCESS is thrown sometimes with the following call stack:

1 0x69290f9 StartWebThread()
2 0x2aad6b0 __pthread_once_handler
3 0x2a9eebe _os_once
4 0x2aad65f pthread_once
5 0x6928e8e WebThreadEnable
6 0x57fd32a +[WebView(WebPrivate) enableWebThread]
7 0x57fa090 WebKitInitialize
8 0x739330 ___UIApplicationLoadWebKit_block_invoke
9 0x2752bef _dispatch_client_callout
10 0x273ca92 dispatch_once_f
11 0x273c922 dispatch_once
12 0x739240 _UIApplicationLoadWebKit
13 0x1e31461 _class_initialize
14 0x1e39fe5 lookUpImpOrForward
15 0x1e39e8d _class_lookupMethodAndLoadCache3
16 0x1e4412f objc_msgSend
17 0x1e2f597 _class_resolveMethod
18 0x1e3a018 lookUpImpOrForward
19 0x1e39e41 lookUpImpOrNil
20 0x1e2f94c class_respondsToSelector
21 0x19d8163 +[NSBundle bundleForClass:]
22 0x190d2e6 -[ObjectMapper populateClassNamesFromMainBundle]
23 0x190ca1d -[ObjectMapper init]
...
27 0x27305ea _dispatch_call_block_and_release
28 0x2752bef _dispatch_client_callout
29 0x273a1ef _dispatch_root_queue_drain
30 0x273bb70 _dispatch_worker_thread3
31 0x2aae1da _pthread_wqthread

The offending line is:
if ([NSBundle bundleForClass:class] == [NSBundle mainBundle])
in populateClassNamesFromMainBunde where class is sometimes_UICompatibilityTextView or UIWebDocumentView or others (varies on each occurrence). It seems to be classes related to WebKit.
This is Xcode 6.2 although it happens on 6.1 as well with iOS 8.1 target.

Alamofire extension for Alamofire 3.x

Hi!

I see there is an Alamofire Request extension example in the README, but if I'm correct it is not for the newest, 3.x version of Alamofire. Can you update it to show how can OCMapper be used with Alamofire 3.x. It would be really appreciated!

Array of Custom objects

I have an array of treatments. The class name is ICATreatment. The mapper maps the array to dictionary correctly, but fails to map from dictionary to array.

Manual setting of mapping provider to return currentNode is needed to prevent empty fetched data from JSON

I have 2 model classes

@interface PBQuiz : NSObject <OCMapperConfigurable>

@property (nonatomic, strong) NSString* name;
@property (nonatomic, strong) NSString* image;
@property (nonatomic, strong) NSNumber* weight;
@property (nonatomic, strong) NSArray<NSString*>* tags;
@property (nonatomic, strong) NSString* desc;
@property (nonatomic, strong) NSString* descriptionImage;
@property (nonatomic, strong) NSString* quizId;

@end

and

@interface PBQuizDetail : PBQuiz <OCMapperConfigurable>

@property (nonatomic, strong) NSDate* dateStart;
@property (nonatomic, strong) NSDate* dateExpire;
@property (nonatomic, strong) PBQuizType* type;
@property (nonatomic, strong) NSArray<PBQuizGrade*>* quizGrades;
@property (nonatomic, strong) NSNumber* status;
@property (nonatomic, strong) NSNumber* questionOrder;
@property (nonatomic, strong) NSNumber* deleted;
@property (nonatomic, strong) NSNumber* totalMaxScore;
@property (nonatomic, strong) NSNumber* totalQuestions;
@property (nonatomic, strong) NSNumber* questions;
@property (nonatomic, strong) NSNumber* totalScore;
@property (nonatomic, strong) NSDate* dateJoin;

@end

I have to manually add the following code

[mappingProvider mapFromDictionaryKey:@"grades" toPropertyKey:@"grades" forClass:[PBQuizDetail class] withTransformer:^id(id currentNode, id parentNode) {
        return currentNode;
    }];

just to return currentNode in order to receive value from JSON. If I didn't do this, I will always get 0 elements. Interesting thing also is that it's marked as JKArray type when I see it in debugger. I also use JSONKit. I'm not sure if OCMapper is conflict with JSONKit and cause this issue.

Note, OCMapperConfigurable is just protocol I use which has no effect of this issue.

How to use InCodeMappingProvider with swift

Hi,

I'm not sure this question is relevant but how do you use:

  • (void)mapFromDictionaryKey:(NSString *)dictionaryKey toPropertyKey:(NSString *)propertyKey forClass:(Class)class withTransformer:(MappingTransformer)transformer;

in swift?

I always got the following error: Argument withTransformer must precede argument forClass.

Could you post an example of this method used in Swift please.

Thanks.

Nested array mapping

Hi!

First of all, thanks for the library!

I have a question though. How can I map a nested array with a custom mapped filed? I'll explain with example below.

Having the following json object:

{
"name": "Name",
"associateTags": [
{
"id": 1,
"tagName": "Tag Name"
}
]
}

And the models:

@interface Tag

@Property (nonatomic, strong) NSString *id;
@Property (nonatomic, strong) NSArray *tagName;
@EnD

@interface OuterModel

@Property (nonatomic, strong) NSString *name;
@Property (nonatomic, strong) NSArray *tags;
@EnD

And OuterModel.tags property is mapped as the following:

@"tags":@"associateTags"

The problem is that instead of instantiating NSArray of Tag classes (using the mapped values) it seems like OCMapper tries to instantiate AssociateTag classes.

I've currently ended with renaming Tag model to AssociateTag however it means I'm bound to server side model naming. Having an ability to name classes according to custom mapping would be great. Is this something that is supported or I'm missing something? If it's not supported right now, can you please point the right direction to update the code of the library (class/method name)?

Thanks!

Make automatic conversion between underscores and camelCase optional

You added automatic conversion from underscores to camelCase in 2.1 (#31), which is great but I think it would be better if it is optional.

I mean, if a property with underscore case found, parse the json node to that, and only try to parse to a camelCase one if a parameter with the exact same underscore case-d name not found.

ManagedObjectInstanceProvider.emptyInstanceForClass() issue with Swift

Hi,

I reach the point where one of my swift class is calling the following:

self.mapper.objectFromSource(JSON, toInstanceOfClass:MySwiftClass.self)

In the method of class ManagedObjectInstanceProvider:

- (id)emptyInstanceForClass:(Class)class

the call to:

[NSEntityDescription entityForName:NSStringFromClass(class)  inManagedObjectContext:self.managedObjectContext];

will always return nil cause the result of NSStringFromClass(class) will be something like:

"ProjectName.ClassName"

In Objective C, the above method will return an entityDescription if the entityForName parameter is "ClassName".

Do you have an idea on how I can make that call working?

Thanks.

Feature Request: Can OCMapper figure out the property/var type automatically?

Right now we're using mapFromDictionaryKey() to map a variable to the class type which works fairly well. But, as I remember in Android GSON will automatically detect the type and just parse it using that class.

Just curious - is there a way OCMapper can figure this out itself?

ie: any way OCMapper could figure out that homeTeam variable is of class type GameStatusTeam and not require the mapping below?

    var homeTeam: GameStatusTeam?

...

        mapper().mapFromDictionaryKey("homeTeam", toPropertyKey:"homeTeam", withObjectType:GameStatusTeam.self, forClass:GameStatus.self);

class keyword causes issues withIn the subclassed objective-c class

I've been using OCMapper in Swift and I've run into a compilation problem. This may be an issue with XCode/Swift/Objective-C, but I figured I would open an issue here.

All was working well until I tried to subclass a custom Objective-C class that I had created (a subclass of UIViewController). When I tried to do this, I ran into a build error which pointed to OCMapper.

screenshot 2015-05-20 11 58 55
screenshot 2015-05-20 11 57 26

Not subclassing the custom Objective-C class makes the build error go away (even if I still do the import).

Any ideas?

Nested json keys

Hi

I'm trying to map a composite object like this

   mappingProvider.mapFromDictionaryKey("user.name", toPropertyKey: "name", forClass: User.self)

But it doesn't map, nested keys are not supported?

Implement conversion from flat data to structured data

Add feature to be able to convert flat data (from NSDictionary) to Structured Object:

FROM NSDICTIONARY
id
firstName
lastName
street
city
country
zipCode

TO COMPLEX OBJEXT
User
____id
____firsname
____lastname
____address
___________city
___________country
___________zipCode

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.