设为首页 加入收藏

TOP

【疯狂造轮子-iOS】JSON转Model系列之二(一)
2017-10-13 10:09:32 】 浏览:325
Tags:疯狂 轮子 -iOS JSON Model 系列 之二

【疯狂造轮子-iOS】JSON转Model系列之二

本文转载请注明出处 —— polobymulberry-博客园


1. 前言


上一篇《【疯狂造轮子-iOS】JSON转Model系列之一》实现了一个简陋的JSON转Model的库,不过还存在很多问题。下面我会尝试一个个去解决。

2. 存在问题及解决思路


2.1 没有考虑JSON数据并不一定是NSDictionary类型

有时候JSON并不一定是NSDictionary类型,可能是一个字符串,也可能是NSData类型的数据。不过不管是哪种类型,统统先将其转化为NSData数据,然后使用+[NSJSONSerialization JSONObjectWithData:options:error:]来转化。所以我在initWithAttributes:上面又封装了一层。

- (instancetype)initWithJSONData:(id)json
{
    NSDictionary *dict = [self pjx_dictionaryWithJSON:json];
    return [self initWithAttributes:dict];
}

/**
 * @brief 将NSString和NSData格式的json数据转化为NSDictionary类型
 */
- (NSDictionary *)pjx_dictionaryWithJSON:(id)json
{
    if (!json) {
        return nil;
    }
    // 若是NSDictionary类型,直接返回
    if ([json isKindOfClass:[NSDictionary class]]) {
        return json;
    }
    
    NSDictionary *dict = nil;
    NSData *jsonData = nil;
    
    if ([json isKindOfClass:[NSString class]]) {
        // 如果是NSString,就先转化为NSData
        jsonData = [(NSString*)json dataUsingEncoding:NSUTF8StringEncoding];
    } else if ([json isKindOfClass:[NSData class]]) {
        jsonData = json;
    }
    
    if (jsonData && [jsonData isKindOfClass:[NSData class]]) {
        // 如果时NSData类型,使用NSJSONSerialization
        NSError *error = nil;
        dict = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
        if (error) {
            NSLog(@"pjx_dictionaryWithJSON error:%@", error);
            return nil;
        }
        if (![dict isKindOfClass:[NSDictionary class]]) {
            return nil;
        }
    }
    
    return dict;
}

为此,我在ViewController添加了两个sample。分别用来解析NSString类型的JSON数据和NSData类型的JSON数据。

// NSString类型的JSON数据
- (void)runSimpleSample2
{
    NSString *userStr = @"                                                              \
                        {                                                               \
                            \"username\"       : \"shuaige\",                           \
                            \"password\"       : \"123456\",                            \
                            \"avatarImageURL\" : \"http://www.example.com/shuaige.png\" \
                        }";
    
    PJXUser *user = [[PJXUser alloc] initWithJSONData:userStr];
    
    NSLog(@"runSimpleSample2\n");
    NSLog(@"----------------------------------------");
    NSLog(@"username:%@\n",user.username);
    NSLog(@"password:%@\n",user.password);
    NSLog(@"avatarImageURL:%@\n",user.avatarImageURL);
}

// NSData类型的JSON数据
- (void)runSimpleSample3
{
    NSString *userInfoFilePath = [[NSBundle mainBundle] pathForResource:@"UserInfo" ofType:@"txt"];
    NSData *data = [NSData dataWithContentsOfFile:userInfoFilePath];
    PJXUser *user = [[PJXUser alloc] initWithJSONData:data];
    
    NSLog(@"runSimpleSample3\n");
    NSLog(@"----------------------------------------");
    NSLog(@"username:%@\n",user.username);
    NSLog(@"password:%@\n",user.password);
    NSLog(@"avatarImageURL:%@\n",user.avatarImageURL);
}

输出结果也是正确的:

image

2.2 没有考虑用户传入的JSON数据的key值和property的名称不一致

我第一反应是使用一个映射表。也就是说用户使用时需要自定义一套property和key的映射表。YYModel中使用了一个+ (NSDictionary *)modelCustomPropertyMapper函数,用户可以自定义该函数达到映射表的效果,而这个函数是放在一个protocol中的。我挺认同这种设计的,因为modelCustomPropertyMapper这种函数和Model是一种组合关系,可有可无(optional),所以设计成协议更合适。但是作者在设计protocol又说了一句:

// There's no need to add '<YYModel>' to your class header.
@protocol YYModel <NSObject>

什么意思呢,就是说你自定义一个NSObject子类(如YYBook)时,如果想实现自定义的pr

首页 上一页 1 2 3 4 5 6 下一页 尾页 1/6/6
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇【疯狂造轮子-iOS】JSON转Model系.. 下一篇iOS-多线程--介绍NSThread和GCD及..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目