预告 ARC 重写:iOS 实现的 json 数据源的 O-R Mapping

来源:互联网 发布:网络用户的未来发展 编辑:程序博客网 时间:2024/06/17 23:05

iOS 实现的 json 数据源的 O-R Mapping

太阳火神的美丽人生 (http://blog.csdn.net/opengl_es)

本文遵循“署名-非商业用途-保持一致”创作公用协议

转载请保留此句:太阳火神的美丽人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS、Android、Html5、Arduino、pcDuino否则,出自本博客的文章拒绝转载或再转载,谢谢合作。



时隔几年之久,再来看这四天写出的成果,不禁对那时的自已心生敬佩。

想来,现在看这堆风格很合理的代码,也有些难度,

因为,其中有几个 OC 的类继承的点,是不能用常规面向对象继承来理解的,

而是借鉴 Linux 底层中 C 语言实现的对象机制,逐层提取完成。

确实这一部分当时费了很多脑汁!


当时用 MRC 写成,现在 ARC 已经基本取代了 MRC,而 Swift 在今年的稍晚些时侯,也会取代 ARC 成为常规编程语言而应用于实际项目开发中,

所以,在 ARC 尚在的时侯,把这一课补上吧,别留下遗憾,真正开始了 Swift 的时侯,就不会再有心力和驱动力去使用 ARC 了。!#)*$&#^^*


本处仅为预告,至少是否真得能够重写,还看机缘吧。 

------------------------


再挖个坑,这个相对复杂一些,当时花了四天时间,在2010年的时侯,对于Objective-C 的反射机制的研究。

其中的设计思想,大多源自 Android 教父高焕堂先生的基类架构思想,我这里只是取了其中一小点点,拿到iOS上用一用。

曾经参加过高焕堂先生在我们公司讲授的近一个月的Android课程,Android上来说学到什么,都是次要的,最重要的是在架构设计思想上得到了真经。

高焕堂:台湾Android论坛主席,现任亚太地区Android技术大会主席,台湾Android领域框架开发联盟总架构师。发表100多篇Android核心技术文章,出版了6本Android专业技术书籍。专精于Android 核心框架及核心服务程序开发。


以下仅为相关核心类部分,涉及业务逻辑部分均已删除,不便透露。

其它实体类从该基类派生,各子类成员需有如下限定:

 1实体必须继承自BaseEntity,且该实体类成员变量只能是如下类型的对象:

 NSString

 NSNumber

 NSDecimalNumber

 UIImage

 NSArray

 BaseEntity的子类

  2不允许使用NSDictionary,如确需要,可考虑定义对应实体类,且该实体类必须继承自BaseEntity

  3禁止有继承关系的类进行复合、聚集。

        任何循环引用的情况均需考虑是否会造成解析死循环,比如,a对象有一个数组成员,那么该数组的元素不能是a对象及其子类;

  4

       a、数组元素值为NSNull,用空字符串代替

       b、成员变量值为nil,解析会自动忽略该成员

       c、未在 中列出的类及其子类,解析会自动忽略

 

 // 以下类型转成json均协同测试通过

 数值:NSNumber

 整型

 长整型:最多传入10位数字,超过则溢出显示成负数

 单精度

 双精度

 布尔

 日期:NSDate

 字符串:NSString

 图片:UIImage

 数组:NSArray

 对象:BaseEntity的子类


@interface BaseEntity(Private)//图片base64编解码方法- (NSString *)encodeToBase64:(NSData *)toEncodeData;- (NSData *)decodeFromBase64:(NSString *)toDecodeString;- (NSString *)encodeUIImageToBase64:(UIImage *)toEncodeUIImage;- (UIImage *)decodeUIImageFromBase64:(NSString *)toDecodeString;//实体映射到键值- (NSString *)parseAttributeType:(NSString *)Attributes;- (NSArray *)getClassPropertys:(Class)classInstance;- (NSArray *)getAllPropertys:(Class)classInstance;- (NSDictionary *)getAllClassMapping:(Class)classInstance;- (NSArray *)getPropertyList;- (NSDictionary *)getClassMapping;//键值映射到json- (NSString *)generateRandomNumber;- (NSArray *)getArrayContainSubedClass:(NSArray *)dealedArray;- (NSDictionary *)getDictionaryContainedSubClass;@end@implementation BaseEntity#pragma mark - 类生命周期- (id)init{    self = [super init];    if (self) {            }        return self;}- (void)dealloc {        [super dealloc];}#pragma mark - 类属性映射表:各子如需替换json中的键值名,实现该方法+ (NSDictionary *)getMappingDic {        return [NSDictionary dictionaryWithObjectsAndKeys:@"tokenid", @"token", nil];}+ (NSDictionary *)dictionaryPresentationOf:(NSString *)className {        Class subClass = NSClassFromString(className);    BaseEntity *baseEntity = [[subClass alloc] init];    NSDictionary *propertyDic = [NSDictionary dictionaryWithDictionary:[baseEntity dictionaryPresentation]];    [baseEntity release];        return propertyDic;}+ (NSString *)JSONRepresentationOf:(NSString *)className {        Class subClass = NSClassFromString(className);    BaseEntity *baseEntity = [[subClass alloc] init];    NSString *jsonString = [NSString stringWithString:[baseEntity JSONRepresentation]];    [baseEntity release];        return jsonString;}#pragma mark - 图片base64编解码方法- (NSString *)encodeToBase64:(NSData *)toEncodeData {        NSUInteger shouldLength = ([toEncodeData length] + 2) / 3 * 3;    NSUInteger base64Length = shouldLength / 3 * 4 + 1;        char *base64Bytes = malloc(base64Length);    memset(base64Bytes, 0, base64Length);        encodeBase64([toEncodeData bytes], [toEncodeData length], base64Bytes, &base64Length);        NSString *base64String = [[[NSString alloc] initWithUTF8String:base64Bytes] autorelease];        return base64String;}- (NSData *)decodeFromBase64:(NSString *)toDecodeString {        return nil;}- (NSString *)encodeUIImageToBase64:(UIImage *)toEncodeUIImage {    NSData *imageData = UIImagePNGRepresentation(toEncodeUIImage);    return [self encodeToBase64:imageData];}- (UIImage *)decodeUIImageFromBase64:(NSString *)toDecodeString {    return nil;}#pragma mark - 实体映射到键值- (NSString *)parseAttributeType:(NSString *)Attributes {    NSRange leftRange = [Attributes rangeOfString:@"\""];    NSString *temp1 = [Attributes substringFromIndex:leftRange.location+1];    NSRange rightRange = [temp1 rangeOfString:@"\""];    NSString *temp2 = [temp1 substringToIndex:rightRange.location];        return temp2;}// 获取某个类自身的所有属性- (NSArray *)getClassPropertys:(Class)classInstance {    NSMutableArray *classPropertyDics = [[NSMutableArray alloc] init];        u_int count;    objc_property_t *properties  = class_copyPropertyList(classInstance, &count);    for (int i = 0; i < count ; i++) {        const char* propertyName = property_getName(properties[i]);        const char* propertyAttributes = property_getAttributes(properties[i]);        NSString *name = [NSString stringWithUTF8String:propertyName];        NSString *attribute = [NSString stringWithUTF8String:propertyAttributes];        NSString *attributeType = [self parseAttributeType:attribute];                NSMutableDictionary *propertyDic = [[NSMutableDictionary alloc] init];        [propertyDic setObject:attributeType forKey:name];        [classPropertyDics insertObject:propertyDic atIndex:0];        //[propertys addObject: propertyDic];        [propertyDic release];    }    free(properties);        return (NSArray *)classPropertyDics;}// 递归获取该类至其某一层父层(参数指定)的所有类的属性集合- (NSArray *)getAllPropertys:(Class)classInstance {    NSMutableArray *allPropertys = [[[NSMutableArray alloc] init] autorelease];        if (![[[[[classInstance superclass] alloc] init] autorelease] isMemberOfClass:[BaseEntity class]]) {        NSArray *superPropertys = [self getAllPropertys:[classInstance superclass]];        [allPropertys addObjectsFromArray:superPropertys];    }        NSArray *propertys = [self getClassPropertys:classInstance];    [allPropertys addObjectsFromArray:propertys];        return allPropertys;}- (NSDictionary *)getAllClassMapping:(Class)classInstance {    NSMutableDictionary *allMappingDic = [[[NSMutableDictionary alloc] init] autorelease];        if (![[[[[classInstance superclass] alloc] init] autorelease] isMemberOfClass:[BaseEntity class]]) {        NSDictionary *mappingDic = [self getAllClassMapping:[classInstance superclass]];        NSArray *keys = [mappingDic allKeys];        for (NSString *key in keys) {            NSString *value = [mappingDic objectForKey:key];            [allMappingDic setObject:value forKey:key];        }    }            NSDictionary *classMappingDic = (NSDictionary *)[classInstance getMappingDic];    NSArray *keys = [classMappingDic allKeys];    for (NSString *key in keys) {        NSString *value = [classMappingDic objectForKey:key];        [allMappingDic setObject:value forKey:key];    }        return allMappingDic;}- (NSArray *)getPropertyList {    NSArray *propertys = [self getAllPropertys:[self class]];        return propertys;}- (NSDictionary *)getClassMapping {    NSDictionary *mappingDic = [self getAllClassMapping:[self class]];        return mappingDic;}#pragma mark - 键值映射到json- (NSArray *)getArrayContainSubedClass:(NSArray *)dealedArray {    NSMutableArray *outArray = [[[NSMutableArray alloc] init] autorelease];        for (id element in dealedArray) {        if (NO == [element isKindOfClass:[NSNull class]]) {            //字符串            if (YES == [element isKindOfClass:[NSString class]]) {                [outArray addObject:element];            }            //数值            else if (YES == [element isKindOfClass:[NSNumber class]]) {                [outArray addObject:element];            }            //浮点型:暂未用,仅json转成对象时,浮点型会转成此类型            else if (YES == [element isKindOfClass:[NSDecimalNumber class]]) {                [outArray addObject:element];            }            //日期            else if (YES == [element isKindOfClass:[NSDate class]]) {                NSDate *attributeDateValue = (NSDate *)element;                double attributeDoubleValue = [attributeDateValue timeIntervalSince1970];                NSMutableDictionary *specialDic = [[NSMutableDictionary alloc] init];                [specialDic setObject:[NSNumber numberWithLongLong:attributeDoubleValue] forKey:@"time"];                [specialDic setObject:@"java.util.Date" forKey:@"javaClass"];                [outArray addObject:specialDic];                [specialDic release];            }            //图片            else if (YES == [element isKindOfClass:[UIImage class]]) {                NSString *base64String = [self encodeUIImageToBase64:(UIImage *)element];                [outArray addObject:base64String];            }            //数组            else if (YES == [element isKindOfClass:[NSArray class]]) {                NSArray *dealedArray = [self getArrayContainSubedClass:(NSArray *)element];                [outArray addObject:dealedArray];            }            //BaseEntity的子类            else if (YES == [element isKindOfClass:[BaseEntity class]]) {                NSDictionary *objDic = [element getDictionaryContainedSubClass];                [outArray addObject:objDic];            }            else {                //非以上类型的成员,此忽略,并提示开发人员,成员填写需进一步核实                NSLog(@"忽略并且未转换成json的数组元素:%@", element);            }        }        else {            [outArray addObject:@""];        }    }        return outArray;}- (NSDictionary *)getDictionaryContainedSubClass {    NSArray *propertys = [self getPropertyList];    NSDictionary *mappingDic = [self getClassMapping];        NSMutableDictionary *selfDic = [[[NSMutableDictionary alloc] init] autorelease];    for (NSDictionary *elementDic in propertys) {        NSArray *keys = [elementDic allKeys];        //正常来说,该层循环只有一次,特别情况例外(特别情况暂未知,留此接口)        for (NSString *attributeName in keys) {            //映射            NSString *mappingKeyName = [mappingDic objectForKey:attributeName];            if (nil == mappingKeyName) {                mappingKeyName = attributeName;            }                        id attributeValue = [self valueForKey:attributeName];            if (nil != attributeValue) {                //字符串                if (YES == [attributeValue isKindOfClass:[NSString class]]) {                    [selfDic setObject:attributeValue forKey:mappingKeyName];                }                //数值                else if (YES == [attributeValue isKindOfClass:[NSNumber class]]) {                    [selfDic setObject:attributeValue forKey:mappingKeyName];                }                //浮点型:暂未用,仅json转成对象时,浮点型会转成此类型                else if (YES == [attributeValue isKindOfClass:[NSDecimalNumber class]]) {                    [selfDic setObject:attributeValue forKey:mappingKeyName];                }                //日期                else if (YES == [attributeValue isKindOfClass:[NSDate class]]) {                    NSDate *attributeDateValue = (NSDate *)attributeValue;                    double attributeDoubleValue = [attributeDateValue timeIntervalSince1970];                    NSMutableDictionary *specialDic = [[NSMutableDictionary alloc] init];                    [specialDic setObject:[NSNumber numberWithLong:attributeDoubleValue] forKey:@"time"];                    [specialDic setObject:@"java.util.Date" forKey:@"javaClass"];                    [selfDic setObject:specialDic forKey:mappingKeyName];                    [specialDic release];                }                //图片                else if (YES == [attributeValue isKindOfClass:[UIImage class]]) {                    NSString *base64String = [self encodeUIImageToBase64:(UIImage *)attributeValue];                    [selfDic setObject:base64String forKey:mappingKeyName];                }                //数组                else if (YES == [attributeValue isKindOfClass:[NSArray class]]) {                    NSArray *outArray = [self getArrayContainSubedClass:(NSArray *)attributeValue];                    [selfDic setObject:outArray forKey:mappingKeyName];                }                //BaseEntity的子类                else if (YES == [attributeValue isKindOfClass:[BaseEntity class]]) {                    NSDictionary *objDic = [attributeValue getDictionaryContainedSubClass];                    [selfDic setObject:objDic forKey:mappingKeyName];                }                else {                    //非以上类型的成员,此忽略,并提示开发人员,成员填写需进一步核实                    NSLog(@"忽略并且未转换成json的成员:%@", attributeName);                }            }            else {                [selfDic setObject:@"" forKey:mappingKeyName];            }        }    }    return selfDic;}- (NSDictionary *)dictionaryPresentation {    return [self getDictionaryContainedSubClass];}- (NSString *)JSONRepresentation {    NSDictionary *dictionaryPresentationDic = [self dictionaryPresentation];    if ([dictionaryPresentationDic respondsToSelector:@selector(JSONRepresentation)]) {        return [dictionaryPresentationDic JSONRepresentation];    }    else {        return nil;    }}- (NSString *)generateUuidString {    CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);    NSString *uuidString = (NSString*)CFUUIDCreateString(kCFAllocatorDefault, uuid);    [uuidString autorelease];    CFRelease(uuid);    return uuidString;}//按业务实际要求提供随机数算法,本处仅简单使用c语言随机数生成- (NSString *)generateRandomNumber {    int value = (arc4random() % 1000000000) + 1;        return [NSString stringWithFormat:@"%d", value];}- (NSDictionary *)dictionaryPresentation:(NSString *)method {    if (nil != method) {        NSDictionary *businessDic = [self getDictionaryContainedSubClass];        NSString *randomString = [self generateRandomNumber];                NSMutableDictionary *resultDic = [[[NSMutableDictionary alloc] init] autorelease];        [resultDic setObject:randomString forKey:@"id"];        [resultDic setObject:method forKey:@"method"];        NSArray *params = [NSArray arrayWithObject:businessDic];        [resultDic setObject:params forKey:@"params"];                return resultDic;    }    else {        return nil;    }}- (NSString *)JSONRepresentation:(NSString *)method {    NSDictionary *dictionaryPresentationDic = [self dictionaryPresentation:method];    if ([dictionaryPresentationDic respondsToSelector:@selector(JSONRepresentation)]) {        return [dictionaryPresentationDic JSONRepresentation];    }    else {        return nil;    }}- (NSData *)JSONDataRepresentation:(NSString *)method {    NSString *resultJsonString = [self JSONRepresentation:method];        return (NSData *)[NSData dataWithBytes:[resultJsonString UTF8String] length:[resultJsonString lengthOfBytesUsingEncoding:NSUTF8StringEncoding]];}@end


此类是在我马上要出差去北京之前的四天时间里怱忙写成,费了不少脑汁,而且还费了不少口水说服小鬼儿们使用,不过还是得益于严大神的全力支持,感谢感谢再感谢,感谢在这里工作期间,大神对我的关照和支持,别人都觉得您出差不在家了,不用提心吊胆了,真爽!我听到您不在家去差了,心情正好想反,觉得您不在家了,就好像缺点儿什么似的,只要看着您在,我默默地工作,都觉得有底,再难的问题,都觉得能解决,因为即使我解决不了,还有您给指点。

现在每每行事,遇到难题,都会回想起,您当时处事的风格,宽容、大度、淡然、从容、果断、重情义......,随便挑出几样照着做,总会有豁然开朗的心情陪伴,虽然我不愿意也不可能再回去,但总还是忘不了您这位伯乐。

哈哈哈,看官们,上面这段话,也许你们看不懂,但绝对能让我回忆起那段快乐、轻松的时光,也就是在那里,我从战术型思维转入战略型思维,这是过后一些还在那里工作的兄弟们给的评价,慢慢自已发现好像是有这样的变化。

人得学会感恩,因为你感恩,所以你能够拥抱一切,因为你乐于感恩,所以一切也会拥抱你。


0 0
原创粉丝点击