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



我还在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} ....
}
关键字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})
}
}
var json = """
{
"temperature": {
"poolTemp" : 85,
"spaTemp"  : 85,
"airTemp"  : 75
},
"circuit": {
"1": {
"number": 1,
"numberStr": "circuit1",
"name": "SPA"
},
"2": {
"number": 2,
"numberStr": "circuit2",
"name": "POOL LIGHT"
}
}
}
""".data(using: .utf8)!
struct Weather :Codable {
let temperature:Temperature
let circuit:Circuit
}
struct Temperature :Codable{
let poolTemp:Int 
let spaTemp:Int 
let airTemp:Int
}
struct Circuit:Codable {
let one:Circuits 
let two:Circuits
enum CodingKeys:String,CodingKey {
case one = "1" 
case two = "2"
}
}
struct Circuits: Codable {
let number: Int 
let numberStr : String
let name: String
}
do {
let decoder = try JSONDecoder().decode(Weather.self , from: json) 
print(decoder)
}catch {
print("Error decoding Data")
}

最新更新