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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 00:57:12