Swift 4解析数量为1 + n的json数字键

时间:2018-07-10 18:41:38

标签: json swift4

我仍然在Swift 4中学习了Codable/Decodable的新功能,用于JSON解析。

我能够构建一个结构并抓住温度键,但是Pump和其他类似的项目是数字字符串,可能是1到n。将它们解析为数组或字典的最佳方法是什么。我会假设一个for循环吗?

 public struct ServerReponse: Codable {
    let temperature: Temperature
    let circuit: Circuit 
 }

public struct Circuit: Codable {
    let number: Int
    let numberStr: String
    let name: String
    let circuitFunction: String
    let status: Int
    let freeze: Int
    let delay: Int
    let friendlyName: String
    let light: Light?
}

public struct Light: Codable {
    let pump: Int
    let position: Int
    let colorStr: String
    let color: Int
    let colorSet: Int
    let colorSetStr: String
    let prevColor: Int
    let prevColorStr: String
    let colorSwimDelay: Int
    let mode: Int
    let modeStr: String
}

public struct Temperature : Codable {
    let poolTemp: Int
    let airTemp: Int
    let poolSetPoint: Int
    let heaterActive: Int
    }
...
let poolData = try? JSONDecoder().decode(ServerReponse.self, from: data)
print(poolData?.temperature)

我在解析下一节“电路”时遇到问题,其中可能有1到许多数字键,然后电路本身位于每个数字键之下。

这是我正在使用的一些JSON ...

{
"temperature": {
    "poolTemp": 85,
    "spaTemp": 85,
    "airTemp": 75,
    "solarTemp": 0,
    "freeze": 0,
    "poolSetPoint": 82,
    "poolHeatMode": 1,
    "poolHeatModeStr": "Heater",
    "spaSetPoint": 80,
    "spaManualHeatMode": "Off",
    "spaHeatMode": 0,
    "spaHeatModeStr": "OFF",
    "heaterActive": 0
},
"circuit": {
        "1": {
            "number": 1,
            "numberStr": "circuit1",
            "name": "SPA",
            "circuitFunction": "Spa",
            "status": 0,
            "freeze": 0,
            "macro": 0,
            "delay": 0,
            "friendlyName": "SPA"
        },
        "2": {
            "number": 2,
            "numberStr": "circuit2",
            "name": "POOL LIGHT",
            "circuitFunction": "Intellibrite",
            "status": 0,
            "freeze": 0,
            "macro": 0,
            "delay": 0,
            "friendlyName": "POOL LIGHT",
            "light": {
                "position": 1,
                "colorStr": "off",
                "color": 0,
                "colorSet": 12,
                "colorSetStr": "Magenta",
                "prevColor": 0,
                "prevColorStr": "White",
                "colorSwimDelay": 5,
                "mode": 0,
                "modeStr": "Off"
            }
        },
        "3": {
            "number": 3,
            "numberStr": "circuit3",
            "name": "AUX 2",
            "circuitFunction": "Generic",
            "status": 1,
            "freeze": 0,
            "macro": 0,
            "delay": 0,
            "friendlyName": "OUTLET - PINE TREE"
        },
        "4": {
            "number": 4,
            "numberStr": "circuit4",
            "name": "AUX 3",
            "circuitFunction": "Generic",
            "status": 1,
            "freeze": 0,
            "macro": 0,
            "delay": 0,
            "friendlyName": "OUTLET - FOUNTAIN"
        },
        "5": {
            "number": 5,
            "numberStr": "circuit5",
            "name": "AUX 4",
            "circuitFunction": "Generic",
            "status": 0,
            "freeze": 0,
            "macro": 0,
            "delay": 0,
            "friendlyName": "AUX 4"
        },
        "6": {
            "number": 6,
            "numberStr": "circuit6",
            "name": "POOL",
            "circuitFunction": "Pool",
            "status": 1,
            "freeze": 1,
            "macro": 0,
            "delay": 0,
            "friendlyName": "POOL"
        },
      .... {more keys} ....
}

1 个答案:

答案 0 :(得分:2)

circuit的值是一个字典。

如果您需要通过数字快速访问,请将该对象解码为[String:Circuit]

public struct ServerReponse: Codable {
   let temperature: Temperature
   let circuit: [String:Circuit] 
}

如果数组更合适,请编写一个自定义初始化程序,该初始化程序还会将值映射到数组。

public struct ServerReponse: Codable {
    let temperature: Temperature
    let circuits: [Circuit]

    private enum CodingKeys: String, CodingKey { case temperature, circuits = "circuit"}

    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        temperature = try container.decode(Temperature.self, forKey: .temperature)
        let circuitData = try container.decode([String:Circuit].self, forKey: .circuits)
        circuits = Array(circuitData.values).sorted(by: {$0.number < $1.number})
    }
}