in Objective-C Json ~ read.

Object 转 Json (针对父类和数组)

该文章是针对那些不想用第三方框架,却想做到OC转Json的朋友的文章。 关于普通的OC转Json的资料已经非常多了,可是对于其中的转换还是存在一些缺陷,关于其中的缺陷也会在接下来的文章中提到。不过首先我们先看看网络上经常看到的实现方法和实现,并且针对其中的缺陷进行逐一的填补。

首先先看看网络上的实现方法

刚开始做项目的时候暂时还不想用第三方框架,于是就去搜索了如何OC转Json的资料,刚开始哪来用的时候主要是通过以下这些方法来实现

首先第一个方法是下面这个方法。该方法是用于遍历对象中的属性,将其转换为NSDictionary

+ (NSDictionary*)getObjectData:(id)obj {

    NSMutableDictionary *dic = [NSMutableDictionary dictionary];
    unsigned int propsCount;
    objc_property_t *props = class_copyPropertyList([obj class], &propsCount);
    for(int i = 0;i < propsCount; i++)
    {
        objc_property_t prop = props[i];
        NSString *propName = [NSString stringWithUTF8String:property_getName(prop)];
        id value = [obj valueForKey:propName];
        if(value == nil)
        {
            value = [NSNull null];
            continue;
        }
        else
        {
            value = [self getObjectInternal:value];
        }
        [dic setObject:value forKey:propName];
    }
    NSLog(@"123");
    return dic;

}

其次是下面这个方法,显而易见,该方法是讲每个属性的value装换成后,并以key:value的形式存储到NSDictionary中。

+(id)getObjectInternal:(id)obj {
    if([obj isKindOfClass:[NSString class]]
       || [obj isKindOfClass:[NSNumber class]]
       || [obj isKindOfClass:[NSNull class]])
    {
        return obj;
    }
    if([obj isKindOfClass:[NSArray class]])
    {
        NSArray *objarr = obj;
        NSMutableArray *arr = [NSMutableArray arrayWithCapacity:objarr.count];
        for(int i = 0;i < objarr.count; i++)
        {
            [arr setObject:[self getObjectInternal:[objarr objectAtIndex:i]] atIndexedSubscript:i];
        }
        return arr;
    }
    if([obj isKindOfClass:[NSDictionary class]])
    {
        NSDictionary *objdic = obj;
        NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithCapacity:[objdic count]];
        for(NSString *key in objdic.allKeys)
        {
            [dic setObject:[self getObjectInternal:[objdic objectForKey:key]] forKey:key];
        }
        return dic;
    }
    return [self getObjectData:obj];
}

最后只要通过大家都知道的language-objectivec NSJSONSerialization中的dataWithJSONObject:options:error:即可。具体代码如下:

NSData *jsonData = [NSJSONSerialization dataWithJSONObject:[self getObjectData:obj] options:NSJSONWritingPrettyPrinted error:nil];  
    NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];

使用状态

父类属性不见了?

在使用过程中发现父类属性好像转不了,在转换的Json中找不到父类的属性。于是我就开始将目光对准了getObjectData:这个方法。只要将这个方法进行稍微的改装即可。具体改装后见下方:

+ (NSDictionary*)getObjectData:(id)obj {
    NSMutableDictionary *dic = [NSMutableDictionary dictionary];
    unsigned int propsCount;
    Class class = [obj class];
    do { // 加这个do-while是为了将父类的属性页进行遍历
        objc_property_t *props = class_copyPropertyList(class, &propsCount);
        for(int i = 0;i < propsCount; i++)
        {
            objc_property_t prop = props[i];

            NSString *propName = [NSString stringWithUTF8String:property_getName(prop)];
            id value = [obj valueForKey:propName];
            if(value == nil)
            {
                value = [NSNull null];
                continue;
            }
            else
            {
                value = [self getObjectInternal:value];
            }
            [dic setObject:value forKey:propName];
        }
        class = [class superclass];
    } while (class != [NSObject class]);
    return dic;
}

其中主要是加了一个do-while的语句,该语句主要用于遍历父类中的变量直到该遍历到的类的父类为NSObject为止。这样即可对父类的属性进行遍历。

数组(NSArray)不可以转Json?

再使用一段时间后发现数组竟然转不了Json,总会出现转不了Json的情况于是乎又不得不去看看之前的方法有没有进行改善。后来发现只要对NSArray进行遍历一遍,并且加上[,]即可。然后我又对获得NSData后,转NSString进行了如下封装:

+(NSString *)getJSONString:(id)obj {
    NSString *jsonString;
    NSData *jsonData;
    if ([obj isKindOfClass:[NSArray class]] || [obj isKindOfClass:[NSMutableArray class]]) {
        NSString *tmpJson;
        jsonString = @"[";
        for (id object in obj) {
            tmpJson = [self getJSONString:object];
            jsonString = [NSString stringWithFormat:@"%@%@,", jsonString, tmpJson];
        }
        jsonString = [[jsonString substringToIndex:jsonString.length-1] stringByAppendingString:@"]"];
    } else {
        jsonData = [self getJSONData:obj];
        jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    }
    return jsonString;
}

最后,终于可以愉快的玩耍了。 Make it

comments powered by Disqus