如何无需手动配置,从Codable结构体生成含CodingKeys与值的字典?
自动关联Codable结构体属性与CodingKeys生成字典
核心思路
结合反射(Mirror)和CaseIterable协议解决问题:
- 让
CodingKeys遵循CaseIterable,实现所有编码键的遍历 - 通过
Mirror获取结构体的存储属性及其对应值 - 将
CodingKeys的case名称与属性名匹配,最终用CodingKeys的rawValue作为字典键,属性值作为值
通用解决方案(扩展Codable)
为所有遵循Codable且CodingKeys实现CaseIterable的类型添加通用方法:
extension Codable where Self.CodingKeys: CaseIterable { func allValues() -> [String: Any] { let mirror = Mirror(reflecting: self) var keyValueDict = [String: Any]() for codingKey in Self.CodingKeys.allCases { // CodingKeys的case名称对应结构体属性名 let propertyName = String(describing: codingKey) // 从反射结果中匹配属性并取值 if let child = mirror.children.first(where: { $0.label == propertyName }) { keyValueDict[codingKey.rawValue] = child.value } } return keyValueDict } // 如果需要仅返回[String: String]类型的字典 func allStringValues() -> [String: String] { allValues().compactMapValues { $0 as? String } } }
示例使用
修改你的MyStruct,让CodingKeys遵循CaseIterable即可直接调用方法:
struct MyStruct: Codable { let propertyOne: String = "Value One" let propertyTwo: String = "Value Two" // 添加CaseIterable协议 enum CodingKeys: String, CodingKey, CaseIterable { case propertyOne = "Coding Key One" case propertyTwo = "Coding Key Two" } } // 使用示例 let myInstance = MyStruct() print(myInstance.allStringValues()) // 输出:["Coding Key One": "Value One", "Coding Key Two": "Value Two"]
为什么之前的方法不生效?
Mirror只能获取属性的名称标签,无法直接关联到CodingKeys的自定义rawValueCaseIterable能遍历所有CodingKeys,但无法直接获取结构体属性的实际值- 两者结合刚好互补,完成属性值与编码键的映射
内容的提问来源于stack exchange,提问作者EddiKh
相关产品推荐
相关产品推荐

