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

Swift5中如何构造含指定结构双JSON数组的JSON对象?

问题:构建指定结构的JSON对象

初始需求与尝试

目标JSON结构如下(注:原示例中的=为笔误,标准JSON使用:):

{"config": [{"battery_state": "3.12","max_hum": "33","mode": "mode"}], "alarms": [{"1": "12345678"}, {"2": "22334455"}]}

尝试用NSMutableDictionary实现,但结果不符合预期:

let jsonConfigObject: NSMutableDictionary = NSMutableDictionary()
jsonConfigObject.setValue("33" as String, forKey: "max_hum" as String)
jsonConfigObject.setValue("3.12" as String, forKey: "battery_state" as String)
jsonConfigObject.setValue("mode" as String, forKey: "mode" as String)
let arrayConfig = [jsonConfigObject]

var jsonAlarmObject: NSMutableDictionary = NSMutableDictionary()
jsonAlarmObject.setValue("12345678"  as String, forKey: "1"  as String)
var arrayAlarms = [jsonAlarmObject]
jsonAlarmObject = NSMutableDictionary()
jsonAlarmObject.setValue("22334455"  as String, forKey: "2"  as String)
arrayAlarms.append(jsonAlarmObject)

let array = [["config" : arrayConfig], ["alarms" : arrayAlarms]]

得到的错误结果:

[["config": [{"battery_state" = "3.12";"max_hum" = 33;mode = mode;}]], ["alarms": [{1 = 12345678;}, {2 = 22334455;}]]]

后续调整需求(编辑1)

改用Codable结构体尝试:

struct Config: Codable {
    let battery_state, max_hum, mode: String
                         
    enum CodingKeys: String, CodingKey {
        case battery_state = "battery_state"
        case max_hum = "max_hum"
        case mode = "mode"
    }
 }

var conf = Config(battery_state: "0", max_hum: "5", mode: "A")
            
var alarms = [[String:String]]()
alarms.append(["1":"123456"])
alarms.append(["2":"123456"])
alarms.append(["nb_alarms":String(Tag.sharedInstance.nb_alarms)])

得到的结果:

{"config":[{"current_hum":"56","period":"2","battery_level":"2.9"}],"alarms":[{"1":"123456"},{"2":"123456"},{"nb_alarms":"2"}]}

需要的目标结构:

{"config":[{"current_hum":"56","period":"2","battery_level":"2.9"}],"alarms":[{"1":"123456","2":"123456","nb_alarms":"2"}]}

解决方案

针对初始NSMutableDictionary的问题

核心错误是把最终对象构造成了数组包含两个字典,但目标是单个字典包含两个数组键值对。修改如下:

let jsonConfigObject: NSMutableDictionary = NSMutableDictionary()
jsonConfigObject.setValue("33", forKey: "max_hum")
jsonConfigObject.setValue("3.12", forKey: "battery_state")
jsonConfigObject.setValue("mode", forKey: "mode")
let arrayConfig = [jsonConfigObject]

var jsonAlarmObject1: NSMutableDictionary = NSMutableDictionary()
jsonAlarmObject1.setValue("12345678", forKey: "1")
var jsonAlarmObject2: NSMutableDictionary = NSMutableDictionary()
jsonAlarmObject2.setValue("22334455", forKey: "2")
let arrayAlarms = [jsonAlarmObject1, jsonAlarmObject2]

// 关键:构造单个顶级字典,而非数组包裹两个字典
let finalDict = ["config": arrayConfig, "alarms": arrayAlarms]

// 转为标准JSON字符串输出
if let jsonData = try? JSONSerialization.data(withJSONObject: finalDict, options: .prettyPrinted),
   let jsonString = String(data: jsonData, encoding: .utf8) {
    print(jsonString)
}

输出会符合目标结构,JSONSerialization会生成标准:分隔的JSON,而非OC风格的=。

针对编辑1的Codable需求问题

需要alarms数组内只有一个字典,包含所有键值对,而非多个独立字典。修改alarms的构建方式:

struct Config: Codable {
    let current_hum, period, battery_level: String
}

var conf = Config(current_hum: "56", period: "2", battery_level: "2.9")

// 构建单个字典,批量添加所有alarm键值
var alarmDict = [String: String]()
alarmDict["1"] = "123456"
alarmDict["2"] = "123456"
alarmDict["nb_alarms"] = String(Tag.sharedInstance.nb_alarms)
// 数组仅包含这一个字典
let alarms = [alarmDict]

// 定义顶级结构统一管理
struct TopLevel: Codable {
    let config: [Config]
    let alarms: [[String: String]]
}

let topLevel = TopLevel(config: [conf], alarms: alarms)

// 转为JSON字符串输出
if let jsonData = try? JSONEncoder().encode(topLevel),
   let jsonString = String(data: jsonData, encoding: .utf8) {
    print(jsonString)
}

后续添加大量键值时,直接往alarmDict内追加即可,无需重复创建新字典并append到数组。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 15:35:12