Objective-C解析JSON数据并构建对应模型的实现问题求助
Objective-C JSON解析与模型落地实现方案
你现有代码存在几个直接影响解析运行的问题,先列出来:
- 最外层
QTMeme模型漏了JSON结构里的success字段,和返回结构不匹配 - 属性修饰符使用错误:
NSMutableArray类型不能用copy修饰,copy会返回不可变的NSArray实例,调用可变数组方法时会直接崩溃 QTMemeResponse漏了JSON里的id、width、height、box_count字段,现有自定义初始化方法不适合批量JSON解析场景- 没有做类型校验和层级映射逻辑,直接拿原始字典赋值很容易因为类型不匹配、key缺失触发崩溃
第一步:修正模型代码
修正后的QTMeme.h
// 前置声明类,避免编译时类型找不到的报错 @class QTData, QTMemeResponse; @interface QTMeme : NSObject // 补全最外层success字段 @property (nonatomic, assign) BOOL success; @property (nonatomic, strong) QTData *data; // 新增顶层字典转模型初始化方法 - (instancetype)initWithDictionary:(NSDictionary *)dict; @end @interface QTData : NSObject // 注意:可变数组必须用strong修饰,不能用copy @property (nonatomic, strong) NSMutableArray<QTMemeResponse *> *memes; - (instancetype)initWithDictionary:(NSDictionary *)dict; @end @interface QTMemeResponse : NSObject // id是OC关键字,重命名为memeId避免冲突 @property (nonatomic, copy) NSString *memeId; @property (nonatomic, copy) NSString *name; @property (nonatomic, copy) NSString *url; @property (nonatomic, assign) NSInteger width; @property (nonatomic, assign) NSInteger height; @property (nonatomic, assign) NSInteger boxCount; // 保留你原来写的自定义初始化方法 - (instancetype)initMemesWithImage:(NSString *)url withTitle:(NSString *)name; // 新增单条meme字典转模型初始化方法 - (instancetype)initWithDictionary:(NSDictionary *)dict; @end
修正后的QTMeme.m
@implementation QTMeme - (instancetype)initWithDictionary:(NSDictionary *)dict { self = [super init]; if (self) { // 取值前做类型校验,避免类型不匹配崩溃 self.success = [dict[@"success"] boolValue]; NSDictionary *dataDict = dict[@"data"]; if ([dataDict isKindOfClass:[NSDictionary class]]) { self.data = [[QTData alloc] initWithDictionary:dataDict]; } } return self; } @end @implementation QTData - (instancetype)initWithDictionary:(NSDictionary *)dict { self = [super init]; if (self) { self.memes = [NSMutableArray array]; NSArray *memesRawArray = dict[@"memes"]; if ([memesRawArray isKindOfClass:[NSArray class]]) { for (NSDictionary *memeDict in memesRawArray) { if ([memeDict isKindOfClass:[NSDictionary class]]) { QTMemeResponse *meme = [[QTMemeResponse alloc] initWithDictionary:memeDict]; [self.memes addObject:meme]; } } } } return self; } @end @implementation QTMemeResponse - (instancetype)initMemesWithImage:(NSString *)url withTitle:(NSString *)name { self = [super init]; if (self) { self.url = url; self.name = name; } return self; } - (instancetype)initWithDictionary:(NSDictionary *)dict { self = [super init]; if (self) { // 用stringWithFormat兼容服务端返回数字/字符串两种类型的id self.memeId = [NSString stringWithFormat:@"%@", dict[@"id"]]; self.name = dict[@"name"]; self.url = dict[@"url"]; self.width = [dict[@"width"] integerValue]; self.height = [dict[@"height"] integerValue]; self.boxCount = [dict[@"box_count"] integerValue]; } return self; } @end
第二步:在ViewController中完成解析
不管是网络请求返回的NSData还是本地读取的JSON文件,解析逻辑一致:
// 此处jsonData是你拿到的原始JSON二进制数据 NSError *parseError = nil; NSDictionary *jsonRootDict = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&parseError]; if (!parseError && [jsonRootDict isKindOfClass:[NSDictionary class]]) { // 初始化后会自动完成所有层级的模型转换 QTMeme *rootModel = [[QTMeme alloc] initWithDictionary:jsonRootDict]; // 把解析完成的meme数据赋值给你的数据源数组 self.dataSourceArray = [rootModel.data.memes copy]; // 回到主线程刷新UI dispatch_async(dispatch_get_main_queue(), ^{ [self.tableView reloadData]; }); } else { NSLog(@"JSON解析失败:%@", parseError.localizedDescription); }
开发注意点
- 属性修饰符规则:不可变类型(NSString、NSArray、NSDictionary)用
copy修饰,可变类型(NSMutableString、NSMutableArray、NSMutableDictionary)必须用strong修饰 - 类型校验必须加:JSON解析出的对象默认是
id类型,服务端可能出现字段类型返回错误的情况,不做校验直接赋值很容易触发崩溃 - 入门阶段建议先把手写解析逻辑跑通理解原理,后续如果遇到复杂模型映射场景,再考虑用模型转换工具减少重复代码
内容的提问来源于stack exchange,提问作者Dima Bonderzev
相关产品推荐
相关产品推荐

