Swift:JSON请求中关联类型的解包问题处理
解决QValue枚举解包与Codable自定义实现
1. 修正QValue枚举的Codable实现
你的QValue应该是带关联值的枚举,默认Codable会把它编码成带嵌套键的结构(比如{"string": "test"}),要让它直接输出原始值,得自定义编码解码逻辑:
enum QValue { case string(String) case float(Float) case double(Double) case bool(Bool) case int(Int) } extension QValue: Codable { func encode(to encoder: Encoder) throws { let container = encoder.singleValueContainer() switch self { case .string(let val): try container.encode(val) case .float(let val): try container.encode(val) case .double(let val): try container.encode(val) case .bool(let val): try container.encode(val) case .int(let val): try container.encode(val) } } init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() if let val = try? container.decode(String.self) { self = .string(val) } else if let val = try? container.decode(Float.self) { self = .float(val) } else if let val = try? container.decode(Double.self) { self = .double(val) } else if let val = try? container.decode(Bool.self) { self = .bool(val) } else if let val = try? container.decode(Int.self) { self = .int(val) } else { throw DecodingError.dataCorruptedError(in: container, debugDescription: "不支持的QValue类型") } } }
2. 适配FilterValues枚举的编码逻辑
针对qValue(QValue)、qArr([QValue])、qDict([String: QValue])三种情况,让它们编码后直接对应API要求的格式:
enum FilterValues: Codable { case qValue(QValue) case qArr([QValue]) case qDict([String: QValue]) func encode(to encoder: Encoder) throws { switch self { case .qValue(let val): try val.encode(to: encoder) case .qArr(let vals): var container = encoder.unkeyedContainer() for val in vals { try container.encode(val) } case .qDict(let dict): var container = encoder.container(keyedBy: CodingKeys.self) for (key, val) in dict { try container.encode(val, forKey: CodingKeys(stringValue: key)!) } } } init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() if let val = try? QValue(from: decoder) { self = .qValue(val) } else if let arr = try? container.decode([QValue].self) { self = .qArr(arr) } else if let dict = try? container.decode([String: QValue].self) { self = .qDict(dict) } else { throw DecodingError.dataCorruptedError(in: container, debugDescription: "不支持的FilterValues类型") } } private struct CodingKeys: CodingKey { var stringValue: String init?(stringValue: String) { self.stringValue = stringValue } var intValue: Int? init?(intValue: Int) { return nil } } }
3. 验证MASTJsonFilter的编码结果
结构体示例:
struct MASTJsonFilter: Codable { let values: FilterValues // 其他业务属性... }
测试不同场景:
// 生成[String]类型的filter参数 let stringArrFilter = MASTJsonFilter(values: .qArr([.string("apple"), .string("banana")])) // 编码后JSON为 ["apple", "banana"] // 生成[[String: Float]]类型的filter参数 let dictArrFilter = MASTJsonFilter(values: .qArr([.qDict(["min": .float(0), "max": .float(100)])])) // 编码后JSON为 [{"min": 0, "max": 100}]
这样生成的JSON完全匹配API要求,不会有多余的嵌套结构。
内容的提问来源于stack exchange,提问作者triple7
相关产品推荐
相关产品推荐

