Json数据解析后分类思路


代码下载地址:     "大字典 2.zip"


http://vdisk.weibo.com/s/HzjOj





我们这里已从新浪微博中请求回来的数据作为例子。为了让工程简化,我将数据写入到本地了。这里主要是为了学习如何将Json数据解析分类。


新浪微博请求返回来的数据大致格式如下:

{
    "statuses": [
        {
            "created_at": "Tue May 31 17:46:55 +0800 2011",
            "id": 11488058246,
            "text": "求关注。",
            "source": "<a href="http://weibo.com" rel="nofollow">新浪微博</a>",
            "favorited": false,
            "truncated": false,
            "in_reply_to_status_id": "",
            "in_reply_to_user_id": "",
            "in_reply_to_screen_name": "",
            "geo": null,
            "mid": "5612814510546515491",
            "reposts_count": 8,
            "comments_count": 9,
            "annotations": [],
            "user": {
                "id": 1404376560,
                "screen_name": "zaku",
                "name": "zaku",
                "province": "11",
                "city": "5",
                "location": "北京 朝阳区",
                "description": "人生五十年,乃如梦如幻;有生斯有死,壮士复何憾。",
                "url": "http://blog.sina.com.cn/zaku",
                "profile_image_url": "http://tp1.sinaimg.cn/1404376560/50/0/1",
                "domain": "zaku",
                "gender": "m",
                "followers_count": 1204,
                "friends_count": 447,
                "statuses_count": 2908,
                "favourites_count": 0,
                "created_at": "Fri Aug 28 00:00:00 +0800 2009",
                "following": false,
                "allow_all_act_msg": false,
                "remark": "",
                "geo_enabled": true,
                "verified": false,
                "allow_all_comment": true,
                "avatar_large": "http://tp1.sinaimg.cn/1404376560/180/0/1",
                "verified_reason": "",
                "follow_me": false,
                "online_status": 0,
                "bi_followers_count": 215
            }
        },
        ...
    ],
    "previous_cursor": 0,                    // 暂未支持
    "next_cursor": 11488013766,     // 暂未支持
    "total_number": 81655
}



以上的示例来自新浪微博官网。我标出的红色字体 ,是我们JSon解析分类的依据,他们都是字典,也就是说JSon解析分类的思路是按照字典去新建类,类与类之间的嵌套关系和JSon数据的格式相同,这我JSon解析的方法。





我来看一下代码如何实现的:


新建User类用来存放user字典中的内容。

.h文件如下:


#import <Foundation/Foundation.h>
@interface User : NSObject
@property (strong, nonatomic) NSString* screen_name;
-(User*)initWithJsonDictionary:(NSDictionary*)dic;
+(User*)UserWithJsonDictionary:(NSDictionary*)dic;
@end




.m文件如下:

@implementation User
-(User*)initWithJsonDictionary:(NSDictionary *)dic
{
    if (self = [super init]) {
                                                                                                                                 
        self.screen_name = [dic objectForKey:@"screen_name"];
                                                                                                                                
    }
    return self;
}
+(User*)UserWithJsonDictionary:(NSDictionary *)dic
{
      //用这个类方法进行初始化的时候,都会alloc一次,因此就会新分配一块空间
    return [[User alloc] initWithJsonDictionary:dic];
}



新建Status类用来存放statuses字典中的内容。


.h文件如下:

#import <Foundation/Foundation.h>
#import "User.h"
@interface Status : NSObject
@property (strong, nonatomic) NSString* userID;
//将多个字典嵌套的数据取出的思路是为每一个字典对应的建一个数据模型的类
//例如:User类
@property (strong , nonatomic) User* user;
-(Status*)initWithJsonDictionary:(NSDictionary*)dic;
+(Status*)statusWithJsonDictionary:(NSDictionary*)dic;
@end




.m文件如下:

@implementation Status
-(Status*)initWithJsonDictionary:(NSDictionary *)dic
{
    if (self = [super init]) {
        self.userID = [dic objectForKey:@"idstr"];
        NSDictionary* userDic = [dic objectForKey:@"user"];
        if (userDic) {
                                                                                                                     
            self.user = [User UserWithJsonDictionary:userDic];
                                                                                                                     
        }
                                                                                                                 
    }
    return self;
}
+(Status*)statusWithJsonDictionary:(NSDictionary *)dic
{
    //用这个类方法进行初始化的时候,都会alloc一次,因此就会新分配一块空间
    return [[Status alloc] initWithJsonDictionary:dic];
}




为了模拟在真实项目中,获得数据的类和显示数据的类不在一个类中

我们新建一个试图控制器用来显示数据,我们显示数据的位置是在控制台。


OtherViewController.h代码如下:


#import <UIKit/UIKit.h>
@interface OtherViewController : UIViewController
@property (strong , nonatomic) NSArray* statusArr;
@end



OtherViewController.m代码实现如下:

//用来接收通过消息机制发送来的数据
-(void)getArray:(NSNotification*)aNotification
{
    self.statusArr = aNotification.object;
                                                                      
}



- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    //添加一个按钮点击显示数据
    UIButton* btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    btn.frame = CGRectMake(30, 30, 30, 30);
    [self.view addSubview:btn];
    [btn addTarget:self action:@selector(displayUserInfo) forControlEvents:UIControlEventTouchUpInside];
}



-(void)displayUserInfo
{
    Status* status = [self.statusArr objectAtIndex:0];
    NSLog(@"status.userID = %@",status.userID);
    NSLog(@"status.user.screen_name = %@",status.user.screen_name);
}




最后,我们来看一下最后的一个类,我们从这个类中获取数据,获取数据的本地文件在代码例子中。

ViewController.h代码如下:


#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
-(IBAction)changeVC:(id)sender;
@end





ViewController.m文件的代码实现如下:

需要在Xib中拖一个Button与下面的方法相关联


-(IBAction)changeVC:(id)sender
{
    //将JSON格式的数据文件的路径找出
    NSString* path = [[NSBundle mainBundle] pathForResource:@"jsonTest" ofType:@"json"];
    //将数据放入NSData中
    NSData* data = [NSData dataWithContentsOfFile:path];
    //JSON解析
    NSDictionary* dic =  [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
//    NSLog(@"dic = %@",dic);
                                           
    NSArray* arr = [dic objectForKey:@"statuses"];
    NSLog(@"%d",arr.count);
    NSLog(@"arr = %@",arr);
                                              
                                              
    //初始化一个数组
    NSMutableArray* tempArr = [NSMutableArray array];
    //将数组中的字典放入Status模型中,大家在这里会有一个疑问将数组中的字典都放入模型中,怎么区分不同数组中的数据?
    for (NSDictionary* item in arr) {
        //答案在statusWithJsonDictionary:的类方法中见该方法注释
        Status* status = [Status statusWithJsonDictionary:item];
        NSLog(@"item = %@ ",item);
                                                  
                                                  
                                                  
        //将Status类型的对象放入数组中
        [tempArr addObject:status];
    }
    //将tempArr数组通过消息中心发送到@"getArray" 这个名字的消息对应的方法中
    [[NSNotificationCenter defaultCenter] postNotificationName:@"getArray" object:tempArr];
                                              
                                              
                                              
                                              
    //切换视图控制器
    [[NSNotificationCenter defaultCenter] postNotificationName:@"changeVC" object:nil];
}