Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
367 views
in Technique[技术] by (71.8m points)

swift4 - Swift 4 parsing json numeric keys with 1+n amount

I still learning this Codable/Decodable new in Swift 4 for JSON parsing.

I am able to build a struct and grab the temperature keys but the Pump and other items like it are numeric strings that could be 1 to n. What is the best way to parse those into an array or dictionary. I would assume a for loop?

 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)

I am having issues parsing the next section "circuit" where there could be 1 to many number keys then the circuit struc itself below each one of those.

Here is some of the JSON I am working with...

{
"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} ....
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The value for key circuit is a dictionary.

If you need fast access by number decode the object as [String:Circuit]

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

If an array is more suitable write a custom initializer which additionally maps the values to an array.

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})
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...