我正在尝试从该网址https://jsonodds.com/api/test/odds
解码此JSON有时某些值是nil,我想避免将所有属性都设为可选,所以我尝试实现自定义解码。
[
{
"ID": "e83bf033-dbde-49ac-a073-d385ebdc66d1",
"HomeTeam": "Xavier",
"AwayTeam": "Marquette",
"Sport": 2,
"MatchTime": "2018-01-24T23:30:00",
"Odds": [
{
"ID": "50742eed-a1c8-4958-8678-50627ffb665e",
"EventID": "e83bf033-dbde-49ac-a073-d385ebdc66d1",
"MoneyLineHome": "0",
"MoneyLineAway": "0",
"PointSpreadHome": "-4.0",
"PointSpreadAway": "4.0",
"PointSpreadHomeLine": "-110",
"PointSpreadAwayLine": "-110",
"TotalNumber": "78.0",
"OverLine": "-115",
"UnderLine": "-105",
"DrawLine": "0",
"LastUpdated": "2018-01-24T20:50:17",
"SiteID": 3,
"OddType": "First Half"
},
{
"ID": "e83bf033-dbde-49ac-a073-d385ebdc66d1",
"EventID": "e83bf033-dbde-49ac-a073-d385ebdc66d1",
"MoneyLineHome": "-305",
"MoneyLineAway": "255",
"PointSpreadHome": "-7.0",
"PointSpreadAway": "7.0",
"PointSpreadHomeLine": "-112",
"PointSpreadAwayLine": "-108",
"TotalNumber": "162.5",
"OverLine": "-104",
"UnderLine": "-116",
"DrawLine": "0",
"LastUpdated": "2018-01-24T20:50:17",
"SiteID": 3,
"OddType": "Game"
}
],
"Details": "Marquette at Xavier",
"HomeROT": "720",
"AwayROT": "719"
},
我目前有这个,但是我不知道我是否在计算值何时为nil,并且由于JSON中的“ Odds”键是一个数组,因此也很难使它起作用,所以我不确定如何去做。当JSON中的“ OddType”等于“ Game”时,我仅需要“ Odds”。在我从JSON中获取所有数据之后,我只是要过滤掉该内容,因为我不确定解析JSON时是否有办法做到这一点。
struct GameInformation: Codable {
let homeTeam: String
let awayTeam: String
let sport: Int
let matchTime: String
let odds: [Odds]
let details: String
}
struct Odds: Codable {
let moneyLineHome: String
let moneyLineAway: String
let pointSpreadHome: String
let pointSpreadAway: String
let pointSpreadHomeLine: String
let pointSpreadAwayLine: String
let totalNumber: String
let overLine: String
let underLine: String
let drawLine: String
let lastUpdated: String
let oddType: String
}
extension Odds {
enum CodingKeys: String, CodingKey {
case moneyLineHome = "MoneyLineHome"
case moneyLineAway = "MoneyLineAway"
case pointSpreadHome = "PointSpreadHome"
case pointSpreadAway = "PointSpreadAway"
case pointSpreadHomeLine = "PointSpreadHomeLine"
case pointSpreadAwayLine = "PointSpreadAwayLine"
case totalNumber = "TotalNumber"
case overLine = "OverLine"
case underLine = "UnderLine"
case drawLine = "DrawLine"
case lastUpdated = "LastUpdated"
case oddType = "OddType"
}
enum OddsKey: String, CodingKey {
case odds = "Odds"
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: OddsKey.self)
let oddsContainer = try container.nestedContainer(keyedBy: CodingKeys.self, forKey: .odds)
moneyLineHome = try oddsContainer.decodeIfPresent(String.self, forKey: .moneyLineHome) ?? "N/A"
moneyLineAway = try oddsContainer.decodeIfPresent(String.self, forKey: .moneyLineAway) ?? "N/A"
pointSpreadHome = try oddsContainer.decodeIfPresent(String.self, forKey: .pointSpreadHome) ?? "N/A"
pointSpreadAway = try oddsContainer.decodeIfPresent(String.self, forKey: .pointSpreadAway) ?? "N/A"
pointSpreadHomeLine = try oddsContainer.decodeIfPresent(String.self, forKey: .pointSpreadHomeLine) ?? "N/A"
pointSpreadAwayLine = try oddsContainer.decodeIfPresent(String.self, forKey: .pointSpreadAwayLine) ?? "N/A"
totalNumber = try oddsContainer.decodeIfPresent(String.self, forKey: .totalNumber) ?? "N/A"
overLine = try oddsContainer.decodeIfPresent(String.self, forKey: .overLine) ?? "N/A"
underLine = try oddsContainer.decodeIfPresent(String.self, forKey: .underLine) ?? "N/A"
drawLine = try oddsContainer.decodeIfPresent(String.self, forKey: .drawLine) ?? "N/A"
lastUpdated = try oddsContainer.decodeIfPresent(String.self, forKey: .lastUpdated) ?? "N/A"
oddType = try oddsContainer.decodeIfPresent(String.self, forKey: .oddType) ?? "N/A"
}
}
extension GameInformation {
enum CodingKeys: String, CodingKey {
case homeTeam = "HomeTeam"
case awayTeam = "AwayTeam"
case sport = "Sport"
case matchTime = "MatchTime"
case odds = "Odds"
case details = "Details"
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
homeTeam = try container.decodeIfPresent(String.self, forKey: .homeTeam) ?? "N/A"
awayTeam = try container.decodeIfPresent(String.self, forKey: .awayTeam) ?? "N/A"
sport = try container.decodeIfPresent(Int.self, forKey: .sport) ?? 20
matchTime = try container.decodeIfPresent(String.self, forKey: .matchTime) ?? "N/A"
details = try container.decodeIfPresent(String.self, forKey: .details) ?? "N/A"
odds = [try Odds(from: decoder)]
}
}
非常感谢您的帮助!
答案 0 :(得分:0)
尝试在GameInformation初始化中像这样设置赔率:
odds = try container.decode(Array<Odds>.self, forKey: .odds)
接下来,您应该删除OddsKey枚举并更新Odds init:
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
moneyLineHome = try container.decodeIfPresent(String.self, forKey: .moneyLineHome) ?? "N/A"
moneyLineAway = try container.decodeIfPresent(String.self, forKey: .moneyLineAway) ?? "N/A"
pointSpreadHome = try container.decodeIfPresent(String.self, forKey: .pointSpreadHome) ?? "N/A"
pointSpreadAway = try container.decodeIfPresent(String.self, forKey: .pointSpreadAway) ?? "N/A"
pointSpreadHomeLine = try container.decodeIfPresent(String.self, forKey: .pointSpreadHomeLine) ?? "N/A"
pointSpreadAwayLine = try container.decodeIfPresent(String.self, forKey: .pointSpreadAwayLine) ?? "N/A"
totalNumber = try container.decodeIfPresent(String.self, forKey: .totalNumber) ?? "N/A"
overLine = try container.decodeIfPresent(String.self, forKey: .overLine) ?? "N/A"
underLine = try container.decodeIfPresent(String.self, forKey: .underLine) ?? "N/A"
drawLine = try container.decodeIfPresent(String.self, forKey: .drawLine) ?? "N/A"
lastUpdated = try container.decodeIfPresent(String.self, forKey: .lastUpdated) ?? "N/A"
oddType = try container.decodeIfPresent(String.self, forKey: .oddType) ?? "N/A"
}
我还没有测试过,但是应该可以。问题是,我们应该将赔率解析为init内的单个对象,并将其解析为GameInformation init内的集合。我希望这是有道理的。
我认为最好在解析后进行过滤,您可以在GameInformation init中初始化这样的赔率(但如果不使用可选选项,这似乎是不正确的):
odds = try container.decode(Array<Odds>.self, forKey: .odds).filter {
let mirror = Mirror(reflecting: $0)
return !mirror.children.contains(where: { _, value in
if let v = value as? String, v == "N/A" {
return true
} else {
return false
}
})
}