SFMapping 0.0.4

SFMapping 0.0.4

测试已测试
语言语言 Obj-CObjective C
许可证 MIT
发布上次发布2015年4月

Paul Taykalo 维护。



SFMapping 0.0.4

  • 作者:
  • Paul Taykalo

SFObjectMapping


将字典解析为对象的对象映射

安装

使用 CocoaPods

pod 'SFMapping', :git => 'https://github.com/stanfy/SFObjectMapping.git', :tag => '0.0.3'

使用

使用 JSONKit 解析 JSON 到字典很方便,但如何将字典解析到模型呢?

很简单!如下所示

SMBaseObject *parsedObject = [SFMappingCore instanceOfClass:[SMBaseObject class] fromObject:dictionary];

您只需要创建 SMBaseObject 并将字典的键路径映射到属性名称。

实现

SFBaseObject.h

@interface SFBaseObject : NSObject
@property (nonatomic, strong) NSString * ID;
@end

在您代码中更合适的地方设置 SFBaseObject 的映射,格式为 属性名称 - 键路径

#import "SFMapping.h"
#import "NSObject+SFMapping.h"
+ (void)setupMappingsForModelObjects {
    [SFBaseObject setSFMappingInfo:
      [SFMapping property:@"ID" toKeyPath:@"id"],
    nil];
}

简单属性

让我们看看不同简单属性的映射

@property (nonatomic, strong) NSString * pString;
@property (nonatomic, strong) NSNumber * pNumber;
@property (nonatomic, assign) BOOL pBoolean;

映射

#import "SFMapping.h"
#import "NSObject+SFMapping.h"
+ (void)setupMappingsForModelObjects {
    [SFBaseObject setSFMappingInfo:
    [SFMapping property:@"pString" toKeyPath:@"someStringFromDictionary"],
        [SFMapping property:@"pNumber" toKeyPath:@"someNumberFromDictionary"],
        [SFMapping property:@"pBoolean" toKeyPath:@"someBooleanFromDictionary"],  
    nil];
}

数组

如果 SFObjectWithArraySFArrayItem 对象的数组

@interface SFObjectWithArray : NSObject
@property (nonatomic, strong) NSMutableArray * mutableArray;
@property (nonatomic, strong) NSMutableArray * immutableArray;
@end

映射

#import "SFMapping.h"
#import "NSObject+SFMapping.h"
+ (void)setupMappingsForModelObjects {
        [SFObjectWithArray setSFMappingInfo:
         [SFMapping collection:@"mutableArray" classString:@"NSMutableArray" 
            itemClass:@"SFArrayItem" toKeyPath:@"someMutableArrayFromDictionary"],         
         [SFMapping collection:@"immutableArray" classString:@"NSArray" 
            itemClass:@"SFArrayItem" toKeyPath:@"someArrayFromDictionary"],
         nil];
 }

枚举

typedef NS_ENUM(NSInteger , SFUserGender) {
    SFUserGenderFemale = 0,
    SFUserGenderMale = 1
};

typedef NS_ENUM(NSInteger , SFUserType) {
    SFUserTypeNormal= 0,
    SFUserTypePremium = 1
};

@interface SFUser : NSObject
@property(nonatomic, assign) SFUserGender gender;
@property(nonatomic, assign) SFUserType userType;
@property(nonatomic, copy) NSString * name;
@end

有两个建议的映射属性的方法。
第一个是使用全局映射器与假类名注册
第二个是从映射定义中直接使用自定义映射器

映射 #1. 使用全局映射器

/*
Register global mapper for all types of SFUserGender
 */
NSDictionary *userGenderDictionary =
    @{@"female" : @(SFUserGenderFemale),
        @"male" : @(SFUserGenderMale)
    };

// Registering mapper for fake class named SFUserGender
[SFMappingCore registerMapper:
    [SFBlockBasedMapper mapperWithValueTransformBlock:^id(SFMapping *mapping, id value) {
        return value ? userGenderDictionary[value] : nil;
    }] forClass:@"SFUserGender"];

[SFUser setSFMappingInfo:
    // Here we're specifying this property "class", since we registered global mapper for this class previously
    [SFMapping property:@"gender" classString:@"SFUserGender"],       // gender in JSON
    // ....
    nil
];

映射 #2. 使用自定义映射器

NSDictionary *userTypeDictionary =
    @{@"premium" : @(SFUserTypePremium),
        @"normal" : @(SFUserTypeNormal)
    };

[SFUser setSFMappingInfo:
    // ,,, 
    // Here we're specifying local mapper which is used only for this mapping
    [SFMapping property:@"userType" keyPath:@"type" valueBlock:^id(SFMapping *mapping, id value) {
       return value ? userTypeDictionary[value] : nil;;
    }],
    nil
];

对象

如果对象有对 SFAnotherObject 的引用

@property (nonatomic, strong) SFAnotherObject * anotherObject;

映射

+ (void)setupMappingsForModelObjects {
    [SFBaseObject setSFMappingInfo:
         [SFMapping property:@"anotherObject" toKeyPath:@"someObjectKeyPath"],
    nil];
}

在这种情况下,映射器将尝试创建 SFAnotherObject 并按照提供的规则应用映射。
如果没有找到 SFAnotherObject 的映射,则将创建空对象 [SFAnotherObject new]
如果找到了映射,它们将正确应用

日期

对于日期解析,我们建议使用 SFDateMapper
您可以使用预定义的映射器以及一些通用的日期格式

/*
 Format  : EEE, dd MMM yyyy HH:mm:ss z
 locale  : en_US_POSIX
 Timezone: UTC
 */
+ (SFDateMapper *)rfc2882DateTimeMapper;

/*
 Format : yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'
 locale : en_US_POSIX
 Timezone: UTC
 */
+ (SFDateMapper *)rfc3339DateTimeMapper;

/*
 Format : yyyy-MM-dd'T'HH:mm:ssZZZZZ
 locale : en_US_POSIX
 Timezone: Defined by format
 */
+ (SFDateMapper *)iso8601DateTimeMapper;

或者,如果您想创建自己的,可以创建自己的映射器来处理您自己的,专有的日期格式。

// Mapper for dates in timestamp(seconds since 1970) format
+ (id<SFMapper>)timestampMapper {
    static dispatch_once_t once;
    static id<SFMapper> mapper;
    dispatch_once(&once, ^{
        mapper = [SFBlockBasedMapper mapperWithValueTransformBlock:^id(SFMapping *mapping, id value) {
            return [NSDate dateWithTimeIntervalSince1970:[value doubleValue]];
        }];
    });
    return mapper;
}

// Mapper for dates in timestamp("/Date(1302055696487)/") format
+ (id<SFMapper>)dotNetTimestampMapper {
    static dispatch_once_t once;
    static id<SFMapper> mapper;
    dispatch_once(&once, ^{
        static NSCharacterSet *characterSet = [NSCharacterSet characterSetWithCharactersInString:@"/Date()/"];
        mapper = [SFBlockBasedMapper mapperWithValueTransformBlock:^id(SFMapping *mapping, id value) {
            NSString *stringWithTimeStamp = [value stringByTrimmingCharactersInSet:characterSet];
            return [NSDate dateWithTimeIntervalSince1970:[stringWithTimeStamp doubleValue]];
        }];
    });
    return mapper;
}

当日历映射器被选择时

一旦拥有日历映射器,无论是 SFDateMapper 子类,还是一些自定义实现,通常有两种使用方式 - 将其注册为 NSDate 类的全局映射器,或将其设置为要映射的自定义映射器

// Since we know that all dates will be in rfc2882 format,
// We just set global mapper on NSDate class
[SFMappingCore registerMapper:[SFDateMapper rfc2882DateTimeMapper] forClass:@"NSDate"];

[SFActivity setSFMappingInfo:
    // Mapping date by using global date mapper
    [SFMapping property:@"date"],

    // Just in case if we need to map this property differently, we can use custom mapper
    //[[SFMapping property:@"date"] applyCustomMapper:[SFDateMapper rfc3339DateTimeMapper]],
    nil
];
}