如何对键为ObjcType的Swift字典/OrderedDictionary进行JSON编解码?
实现
Dictionary<ObjcType, SwiftType>及OrderedDictionary的JSON编解码 一、修复Objective-C类的序列化方法
你的ObjcType原有序列化/反序列化方法存在逻辑问题,先修正这两个方法:
// 修正序列化方法:将对象属性转为字典后再生成JSON -(NSString*)GetJSON{ NSError *writeError = nil; NSDictionary *propertyDict = @{ @"field1": self.field1 ?: @"", @"field2": self.field2 ?: @"", @"field3": @(self.field3) }; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:propertyDict options:NSJSONWritingPrettyPrinted error:&writeError]; if (writeError) { NSLog(@"JSON序列化失败: %@", writeError.localizedDescription); return @""; } return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; } // 修正反序列化方法:直接从JSON字典中读取字段,而非循环遍历 - (instancetype)initWithObject:(NSString *)jsonString { self = [super init]; if (self != nil) { NSData* jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; NSError *error = nil; NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error]; if (error) { NSLog(@"JSON解析失败: %@", error.localizedDescription); return nil; } self.field1 = jsonDict[@"field1"]; self.field2 = jsonDict[@"field2"]; self.field3 = [jsonDict[@"field3"] boolValue]; } return self; }
二、为ObjcType添加Swift的Codable支持
由于Objective-C类无法直接遵循Swift的Codable协议,通过Swift扩展实现该协议,复用已有的Objective-C方法:
import Foundation extension ObjcType: Codable { // 编码:将ObjcType转为JSON字符串后写入编码器 public func encode(to encoder: Encoder) throws { let jsonString = self.getJSON() // Objective-C方法名在Swift中自动转为小驼峰 var container = encoder.singleValueContainer() try container.encode(jsonString) } // 解码:从JSON字符串初始化ObjcType实例 public init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() let jsonString = try container.decode(String.self) guard let instance = ObjcType(object: jsonString) else { throw DecodingError.dataCorruptedError( in: container, debugDescription: "无法通过JSON字符串初始化ObjcType实例" ) } self = instance } }
三、实现普通Dictionary的编解码
只要ObjcType和SwiftType都遵循Codable,Dictionary<ObjcType, SwiftType>会自动获得Codable支持,直接使用JSONEncoder/JSONDecoder即可:
// 示例SwiftType(已遵循Codable) struct MySwiftType: Codable { let name: String let count: Int } // 1. 创建测试数据 let key1 = ObjcType() key1.field1 = "key_01" key1.field2 = "desc_01" key1.field3 = true let key2 = ObjcType() key2.field1 = "key_02" key2.field2 = "desc_02" key2.field3 = false let testDict: [ObjcType: MySwiftType] = [ key1: MySwiftType(name: "test_01", count: 10), key2: MySwiftType(name: "test_02", count: 20) ] // 2. 序列化 do { let jsonData = try JSONEncoder().encode(testDict) guard let jsonString = String(data: jsonData, encoding: .utf8) else { print("JSON数据转字符串失败") return } print("序列化结果:\n\(jsonString)") } catch { print("序列化错误: \(error.localizedDescription)") } // 3. 反序列化 do { let jsonData = jsonString.data(using: .utf8)! let decodedDict = try JSONDecoder().decode([ObjcType: MySwiftType].self, from: jsonData) print("反序列化结果:\n\(decodedDict)") } catch { print("反序列化错误: \(error.localizedDescription)") }
四、支持OrderedDictionary
只需导入OrderedCollections模块,OrderedDictionary<ObjcType, SwiftType>同样会自动支持Codable,用法与普通字典一致:
import OrderedCollections // 1. 创建有序字典测试数据 let orderedDict = OrderedDictionary<ObjcType, MySwiftType>() orderedDict[key1] = MySwiftType(name: "ordered_test_01", count: 100) orderedDict[key2] = MySwiftType(name: "ordered_test_02", count: 200) // 2. 序列化有序字典 do { let orderedJsonData = try JSONEncoder().encode(orderedDict) guard let orderedJsonString = String(data: orderedJsonData, encoding: .utf8) else { print("有序字典JSON转字符串失败") return } print("有序字典序列化结果:\n\(orderedJsonString)") } catch { print("有序字典序列化错误: \(error.localizedDescription)") } // 3. 反序列化有序字典 do { let orderedJsonData = orderedJsonString.data(using: .utf8)! let decodedOrderedDict = try JSONDecoder().decode(OrderedDictionary<ObjcType, MySwiftType>.self, from: orderedJsonData) print("有序字典反序列化结果:\n\(decodedOrderedDict)") } catch { print("有序字典反序列化错误: \(error.localizedDescription)") }
内容的提问来源于stack exchange,提问作者Afinainflowers
相关产品推荐
相关产品推荐

