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

Swift中结构体数组转Dictionary返回nil问题求助

问题分析与解决方案

首先,咱们来定位问题的核心:你的asDictionary扩展只能处理单个Encodable对象转字典,但你传入的services是[ModelFeedbackServices]数组类型。当你编码数组时,JSONEncoder生成的是JSON数组数据,JSONSerialization.jsonObject返回的是[Any]类型,而你的扩展强行把它转成[String: Any],转换失败自然返回nil。

另外,你期望的参数键名是大写格式(比如SERVICE_ID而非servicesId),当前的结构体没有做键名映射,默认编码出来的键是小驼峰,也不符合需求。

下面是具体的修复步骤:

1. 给结构体添加键名映射(CodingKeys)

修改ModelFeedbackServices结构体,通过CodingKeys枚举把属性名映射到你需要的大写键名:

struct ModelFeedbackServices: Codable {
    let servicesId: String?
    let servicesName: String?
    let category: String?
    
    // 映射到目标键名
    enum CodingKeys: String, CodingKey {
        case servicesId = "SERVICE_ID"
        case servicesName = "SERVICE_NAME"
        case category = "CATEGORY"
    }
}

2. 修改Encodable扩展,支持数组和单个对象

把原来的asDictionary改成能返回任意JSON类型(数组或字典)的扩展,避免强制转字典的限制:

extension Encodable {
    var asJsonValue: Any? {
        guard let data = try? JSONEncoder().encode(self) else { return nil }
        return try? JSONSerialization.jsonObject(with: data, options: .allowFragments)
    }
}

3. 更新参数赋值逻辑

在parameters计算属性里使用新的扩展方法:

var parameters: [String: Any]? {
    var params: [String: Any] = [:]
    switch self {
    case .submit(let services, let comments):
        params["FEEDBACK_SERVICES"] = services.asJsonValue // 现在会正确返回数组
        params["COMMENTS"] = comments
        return params
    }
}

验证效果

这样修改后,生成的参数就会完全符合你的期望:

{
    "FEEDBACK_SERVICES": [
        { "SERVICE_ID": "8", "SERVICE_NAME": "ABC", "CATEGORY": "1" },
        { "SERVICE_ID": "4", "SERVICE_NAME": "ABC", "CATEGORY": "2" }
    ],
    "COMMENTS": "any comment"
}

额外提示:如果需要处理可选值的特殊编码逻辑(比如nil值不省略),可以给JSONEncoder设置outputFormatting或自定义编码逻辑,但当前默认的JSONEncoder行为(忽略nil属性)已经符合你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:31:52