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

iOS Obj-C:如何从含NSArray的对象生成仅保留指定字段的NSDictionary

你的JSON序列化问题拆解与解决方案

嘿,我来帮你理清这个问题的关键点,以及更高效的实现方式:

首先:NSKeyedArchiver不是生成JSON的最佳选择

你现在用NSKeyedArchiver+NSCoding的方式,本质是做二进制归档,它生成的是苹果专属的序列化数据,不是标准JSON。如果你的目标是生成符合示例的JSON结构,直接用NSJSONSerialization配合自定义对象转字典的方法会更直接、更可控,也避免了POD类型转NSObject后还要再转JSON的冗余步骤。

数组元素外层的包裹是否必要?

这完全取决于你的目标JSON结构需求:

  • 如果后端/消费方期望tasks数组里直接存放任务对象(比如[{"name":"Task1", ...}, {...}]),那外层的{"task": {...}}完全没必要,属于多余嵌套;
  • 如果消费方明确要求数组每个元素是一个包含task字段的对象(比如你的示例结构),那这层包裹才是必须的。

简单说:看需求,没有“必须要加”的硬性规则,只看最终JSON的结构约定。

正确实现:自定义对象转字典+JSON序列化

下面是具体的实现思路,能精准控制只保留指定字段,处理POD类型和嵌套数组:

1. 给自定义对象添加转字典的方法

比如你的Task类和SubTask类,分别实现- (NSDictionary *)toDictionary方法,只在方法里暴露需要的字段,同时把POD类型转成NSObject(比如int→NSNumber,bool→NSNumber):

// Task.h
@interface Task : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) int repeat;
@property (nonatomic, strong) NSArray<SubTask *> *subTasks;
- (NSDictionary *)toDictionary;
@end

// Task.m
@implementation Task
- (NSDictionary *)toDictionary {
    // 只保留需要的字段,POD类型转NSNumber
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    dict[@"name"] = self.name;
    dict[@"repeat"] = @(self.repeat);
    
    // 处理嵌套的子任务数组,递归转字典
    NSMutableArray *subTaskDicts = [NSMutableArray array];
    for (SubTask *subTask in self.subTasks) {
        // 如果需要外层包裹sub_task,就把每个子字典包一层:
        // [subTaskDicts addObject:@{@"sub_task": [subTask toDictionary]}];
        // 否则直接添加转好的字典:
        [subTaskDicts addObject:[subTask toDictionary]];
    }
    dict[@"sub_tasks"] = subTaskDicts;
    
    return dict;
}
@end
// SubTask.h
@interface SubTask : NSObject
@property (nonatomic, copy) NSString *subName;
@property (nonatomic, assign) bool isCompleted;
- (NSDictionary *)toDictionary;
@end

// SubTask.m
@implementation SubTask
- (NSDictionary *)toDictionary {
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    dict[@"sub_name"] = self.subName;
    dict[@"is_completed"] = @(self.isCompleted); // bool转NSNumber
    return dict;
}
@end

2. 顶层对象转字典并生成JSON

假设你的顶层对象是一个包含title、revision、tasks的模型:

// 构建顶层字典
NSMutableDictionary *topDict = [NSMutableDictionary dictionary];
topDict[@"title"] = @"My Title";
topDict[@"revision"] = @(1); // int转NSNumber

// 处理tasks数组
NSMutableArray *taskDicts = [NSMutableArray array];
for (Task *task in yourTaskArray) {
    // 如果需要外层包裹task,就包一层:
    // [taskDicts addObject:@{@"task": [task toDictionary]}];
    // 否则直接添加转好的字典:
    [taskDicts addObject:[task toDictionary]];
}
topDict[@"tasks"] = taskDicts;

// 生成JSON数据
NSError *error = nil;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:topDict options:NSJSONWritingPrettyPrinted error:&error];
if (!error) {
    NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    NSLog(@"生成的JSON:%@", jsonString);
} else {
    NSLog(@"JSON生成失败:%@", error.localizedDescription);
}

如果你坚持用NSKeyedArchiver?

如果因为某些原因必须用NSKeyedArchiver,那你需要先把归档后的NSData转成NSDictionary,再转成JSON,但这个过程会引入很多归档的冗余字段(比如$class信息),你需要额外过滤这些字段,非常麻烦,完全不推荐。


内容的提问来源于stack exchange,提问作者DarkMatter

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 03:12:03