You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 11:00:59