在 swift 4 中使用可编码的数组中的嵌套字典键值
nested dictionary keys values in array using codable in swift 4
我在下面的结构中有 json
{
"message": null,
"data": {
"admin": {
"UserId": 1,
"CUSTOMER_PROFILING": {
"id": 0,
"total": 0,
"high": 0,
"low": 0,
"medium": 0
},
"RISK_ASSESSMENT": {
"id": 0,
"total": 0,
"high": 0,
"low": 0,
"medium": 0
},
"LINK_ANALYSIS": {
"id": 0,
"total": 0,
"high": 0,
"low": 0,
"medium": 0
},
"BENCH_MARKING": {
"id": 0,
"total": 0,
"high": 0,
"low": 0,
"medium": 0
},
"SUSPICIOUS_TRANSACTION_REPORTING": {
"id": 0,
"total": 0,
"high": 0,
"low": 0,
"medium": 0
},
"THRESHOLD_TRANSACTION_REPORTING": {
"id": 0,
"total": 0,
"high": 0,
"low": 0,
"medium": 0
}
},
"vinoth59": {
"UserId": 15,
"CUSTOMER_PROFILING": {
"id": 0,
"total": 0,
"high": 0,
"low": 0,
"medium": 0
},
"RISK_ASSESSMENT": {
"id": 0,
"total": 0,
"high": 0,
"low": 0,
"medium": 0
},
"LINK_ANALYSIS": {
"id": 0,
"total": 0,
"high": 0,
"low": 0,
"medium": 0
},
"BENCH_MARKING": {
"id": 0,
"total": 0,
"high": 0,
"low": 0,
"medium": 0
},
"SUSPICIOUS_TRANSACTION_REPORTING": {
"id": 0,
"total": 0,
"high": 0,
"low": 0,
"medium": 0
},
"THRESHOLD_TRANSACTION_REPORTING": {
"id": 0,
"total": 0,
"high": 0,
"low": 0,
"medium": 0
}
},
"ba_user": {
"UserId": 16,
"CUSTOMER_PROFILING": {
"id": 0,
"total": 0,
"high": 0,
"low": 0,
"medium": 0
},
"RISK_ASSESSMENT": {
"id": 0,
"total": 0,
"high": 0,
"low": 0,
"medium": 0
},
"LINK_ANALYSIS": {
"id": 0,
"total": 0,
"high": 0,
"low": 0,
"medium": 0
},
"BENCH_MARKING": {
"id": 0,
"total": 0,
"high": 0,
"low": 0,
"medium": 0
},
"SUSPICIOUS_TRANSACTION_REPORTING": {
"id": 0,
"total": 0,
"high": 0,
"low": 0,
"medium": 0
},
"THRESHOLD_TRANSACTION_REPORTING": {
"id": 0,
"total": 0,
"high": 0,
"low": 0,
"medium": 0
}
}
},
"status": true
}
我的可编码 class 如下所示
struct UserRiskReportBase : Codable {
let message : String?
let data : [String:UserRiskReport]?
let status : Bool?
enum CodingKeys: String, CodingKey {
case message = "message"
case data = "data"
case status = "status"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
message = try values.decodeIfPresent(String.self, forKey: .message)
data = try values.decodeIfPresent([String:[String:BenchMarking]].self, forKey: .data)
status = try values.decodeIfPresent(Bool.self, forKey: .status)
}
}
struct UserRiskReport: Codable {
let userID: Int
let customerProfiling, riskAssessment, linkAnalysis, benchMarking: BenchMarking
let suspiciousTransactionReporting, thresholdTransactionReporting: BenchMarking
enum CodingKeys: String, CodingKey {
case userID = "UserId"
case customerProfiling = "CUSTOMER_PROFILING"
case riskAssessment = "RISK_ASSESSMENT"
case linkAnalysis = "LINK_ANALYSIS"
case benchMarking = "BENCH_MARKING"
case suspiciousTransactionReporting = "SUSPICIOUS_TRANSACTION_REPORTING"
case thresholdTransactionReporting = "THRESHOLD_TRANSACTION_REPORTING"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
userID = try values.decodeIfPresent(Int.self, forKey: .userID)!
customerProfiling = try values.decodeIfPresent(BenchMarking.self, forKey: .customerProfiling)!
benchMarking = try values.decodeIfPresent(BenchMarking.self, forKey: .benchMarking)!
riskAssessment = try values.decodeIfPresent(BenchMarking.self, forKey: .riskAssessment)!
suspiciousTransactionReporting = try values.decodeIfPresent(BenchMarking.self, forKey: .suspiciousTransactionReporting)!
linkAnalysis = try values.decodeIfPresent(BenchMarking.self, forKey: .linkAnalysis)!
thresholdTransactionReporting = try values.decodeIfPresent(BenchMarking.self, forKey: .thresholdTransactionReporting)!
}
}
struct BenchMarking : Codable {
let id : Int?
let total : Int?
let high : Int?
let low : Int?
let medium : Int?
enum CodingKeys: String, CodingKey {
case id = "id"
case total = "total"
case high = "high"
case low = "low"
case medium = "medium"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
id = try values.decodeIfPresent(Int.self, forKey: .id)
total = try values.decodeIfPresent(Int.self, forKey: .total)
high = try values.decodeIfPresent(Int.self, forKey: .high)
low = try values.decodeIfPresent(Int.self, forKey: .low)
medium = try values.decodeIfPresent(Int.self, forKey: .medium)
}
}
我可以获得一级钥匙
let dec = JSONDecoder()
dec.keyDecodingStrategy = .convertFromSnakeCase
let alertList = try dec.decode(UserRiskReportBase.self, from:response.data!)
self.userRiskReportList = alertList.data!
self.headerArr = Array(alertList.data!.keys)
print(self.headerArr)
我得到了一级键,例如 ["admin"、"vinoth59"、"ba_user"]。我需要获得二级密钥 ["CUSTOMER_PROFILING","RISK_ASSESSMENT",.....]。如何实现使用这个codable
下面对我有用,请注意,我做了一些简化并删除了不需要的代码,如 init(from:)
,我还删除了很多属性的可选代码
struct UserRiskReportBase : Codable {
let message : String?
let data : [String:UserRiskReport]
let status : Bool?
}
struct UserRiskReport: Codable {
let userID: Int
let customerProfiling, riskAssessment, linkAnalysis, benchMarking: BenchMarking
let suspiciousTransactionReporting, thresholdTransactionReporting: BenchMarking
enum CodingKeys: String, CodingKey, CaseIterable {
case userID = "UserId"
case customerProfiling = "CUSTOMER_PROFILING"
case riskAssessment = "RISK_ASSESSMENT"
case linkAnalysis = "LINK_ANALYSIS"
case benchMarking = "BENCH_MARKING"
case suspiciousTransactionReporting = "SUSPICIOUS_TRANSACTION_REPORTING"
case thresholdTransactionReporting = "THRESHOLD_TRANSACTION_REPORTING"
}
var allKeys: [String] {
get {
CodingKeys.allCases.map {[=10=].rawValue}
}
}
}
struct BenchMarking : Codable {
let id : Int
let total : Int
let high : Int
let low : Int
let medium : Int
}
do {
let result = try JSONDecoder().decode(UserRiskReportBase.self, from: data)
for item in result.data.values {
print("Report for user: \(item.userID)")
print(item.customerProfiling)
print(item.benchMarking)
//print(...)
}
} catch {
print(error)
}
let dec = JSONDecoder()
dec.keyDecodingStrategy = .useDefaultKeys
let alertList = try? dec.decode(UserRiskReportBase.self, from: respData!)
print("Compelete Data: ", alertList)
let baUser = alertList?.data["ba_user"] as? UserRiskReport
print("ba_user", alertList?.data["ba_user"])
print(baUser?.benchMarking.id)
print(baUser?.thresholdTransactionReporting.total)
记得用.useDefaultKeys
替换.convertFromSnakeCase
我在下面的结构中有 json
{
"message": null,
"data": {
"admin": {
"UserId": 1,
"CUSTOMER_PROFILING": {
"id": 0,
"total": 0,
"high": 0,
"low": 0,
"medium": 0
},
"RISK_ASSESSMENT": {
"id": 0,
"total": 0,
"high": 0,
"low": 0,
"medium": 0
},
"LINK_ANALYSIS": {
"id": 0,
"total": 0,
"high": 0,
"low": 0,
"medium": 0
},
"BENCH_MARKING": {
"id": 0,
"total": 0,
"high": 0,
"low": 0,
"medium": 0
},
"SUSPICIOUS_TRANSACTION_REPORTING": {
"id": 0,
"total": 0,
"high": 0,
"low": 0,
"medium": 0
},
"THRESHOLD_TRANSACTION_REPORTING": {
"id": 0,
"total": 0,
"high": 0,
"low": 0,
"medium": 0
}
},
"vinoth59": {
"UserId": 15,
"CUSTOMER_PROFILING": {
"id": 0,
"total": 0,
"high": 0,
"low": 0,
"medium": 0
},
"RISK_ASSESSMENT": {
"id": 0,
"total": 0,
"high": 0,
"low": 0,
"medium": 0
},
"LINK_ANALYSIS": {
"id": 0,
"total": 0,
"high": 0,
"low": 0,
"medium": 0
},
"BENCH_MARKING": {
"id": 0,
"total": 0,
"high": 0,
"low": 0,
"medium": 0
},
"SUSPICIOUS_TRANSACTION_REPORTING": {
"id": 0,
"total": 0,
"high": 0,
"low": 0,
"medium": 0
},
"THRESHOLD_TRANSACTION_REPORTING": {
"id": 0,
"total": 0,
"high": 0,
"low": 0,
"medium": 0
}
},
"ba_user": {
"UserId": 16,
"CUSTOMER_PROFILING": {
"id": 0,
"total": 0,
"high": 0,
"low": 0,
"medium": 0
},
"RISK_ASSESSMENT": {
"id": 0,
"total": 0,
"high": 0,
"low": 0,
"medium": 0
},
"LINK_ANALYSIS": {
"id": 0,
"total": 0,
"high": 0,
"low": 0,
"medium": 0
},
"BENCH_MARKING": {
"id": 0,
"total": 0,
"high": 0,
"low": 0,
"medium": 0
},
"SUSPICIOUS_TRANSACTION_REPORTING": {
"id": 0,
"total": 0,
"high": 0,
"low": 0,
"medium": 0
},
"THRESHOLD_TRANSACTION_REPORTING": {
"id": 0,
"total": 0,
"high": 0,
"low": 0,
"medium": 0
}
}
},
"status": true
}
我的可编码 class 如下所示
struct UserRiskReportBase : Codable {
let message : String?
let data : [String:UserRiskReport]?
let status : Bool?
enum CodingKeys: String, CodingKey {
case message = "message"
case data = "data"
case status = "status"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
message = try values.decodeIfPresent(String.self, forKey: .message)
data = try values.decodeIfPresent([String:[String:BenchMarking]].self, forKey: .data)
status = try values.decodeIfPresent(Bool.self, forKey: .status)
}
}
struct UserRiskReport: Codable {
let userID: Int
let customerProfiling, riskAssessment, linkAnalysis, benchMarking: BenchMarking
let suspiciousTransactionReporting, thresholdTransactionReporting: BenchMarking
enum CodingKeys: String, CodingKey {
case userID = "UserId"
case customerProfiling = "CUSTOMER_PROFILING"
case riskAssessment = "RISK_ASSESSMENT"
case linkAnalysis = "LINK_ANALYSIS"
case benchMarking = "BENCH_MARKING"
case suspiciousTransactionReporting = "SUSPICIOUS_TRANSACTION_REPORTING"
case thresholdTransactionReporting = "THRESHOLD_TRANSACTION_REPORTING"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
userID = try values.decodeIfPresent(Int.self, forKey: .userID)!
customerProfiling = try values.decodeIfPresent(BenchMarking.self, forKey: .customerProfiling)!
benchMarking = try values.decodeIfPresent(BenchMarking.self, forKey: .benchMarking)!
riskAssessment = try values.decodeIfPresent(BenchMarking.self, forKey: .riskAssessment)!
suspiciousTransactionReporting = try values.decodeIfPresent(BenchMarking.self, forKey: .suspiciousTransactionReporting)!
linkAnalysis = try values.decodeIfPresent(BenchMarking.self, forKey: .linkAnalysis)!
thresholdTransactionReporting = try values.decodeIfPresent(BenchMarking.self, forKey: .thresholdTransactionReporting)!
}
}
struct BenchMarking : Codable {
let id : Int?
let total : Int?
let high : Int?
let low : Int?
let medium : Int?
enum CodingKeys: String, CodingKey {
case id = "id"
case total = "total"
case high = "high"
case low = "low"
case medium = "medium"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
id = try values.decodeIfPresent(Int.self, forKey: .id)
total = try values.decodeIfPresent(Int.self, forKey: .total)
high = try values.decodeIfPresent(Int.self, forKey: .high)
low = try values.decodeIfPresent(Int.self, forKey: .low)
medium = try values.decodeIfPresent(Int.self, forKey: .medium)
}
}
我可以获得一级钥匙
let dec = JSONDecoder()
dec.keyDecodingStrategy = .convertFromSnakeCase
let alertList = try dec.decode(UserRiskReportBase.self, from:response.data!)
self.userRiskReportList = alertList.data!
self.headerArr = Array(alertList.data!.keys)
print(self.headerArr)
我得到了一级键,例如 ["admin"、"vinoth59"、"ba_user"]。我需要获得二级密钥 ["CUSTOMER_PROFILING","RISK_ASSESSMENT",.....]。如何实现使用这个codable
下面对我有用,请注意,我做了一些简化并删除了不需要的代码,如 init(from:)
,我还删除了很多属性的可选代码
struct UserRiskReportBase : Codable {
let message : String?
let data : [String:UserRiskReport]
let status : Bool?
}
struct UserRiskReport: Codable {
let userID: Int
let customerProfiling, riskAssessment, linkAnalysis, benchMarking: BenchMarking
let suspiciousTransactionReporting, thresholdTransactionReporting: BenchMarking
enum CodingKeys: String, CodingKey, CaseIterable {
case userID = "UserId"
case customerProfiling = "CUSTOMER_PROFILING"
case riskAssessment = "RISK_ASSESSMENT"
case linkAnalysis = "LINK_ANALYSIS"
case benchMarking = "BENCH_MARKING"
case suspiciousTransactionReporting = "SUSPICIOUS_TRANSACTION_REPORTING"
case thresholdTransactionReporting = "THRESHOLD_TRANSACTION_REPORTING"
}
var allKeys: [String] {
get {
CodingKeys.allCases.map {[=10=].rawValue}
}
}
}
struct BenchMarking : Codable {
let id : Int
let total : Int
let high : Int
let low : Int
let medium : Int
}
do {
let result = try JSONDecoder().decode(UserRiskReportBase.self, from: data)
for item in result.data.values {
print("Report for user: \(item.userID)")
print(item.customerProfiling)
print(item.benchMarking)
//print(...)
}
} catch {
print(error)
}
let dec = JSONDecoder()
dec.keyDecodingStrategy = .useDefaultKeys
let alertList = try? dec.decode(UserRiskReportBase.self, from: respData!)
print("Compelete Data: ", alertList)
let baUser = alertList?.data["ba_user"] as? UserRiskReport
print("ba_user", alertList?.data["ba_user"])
print(baUser?.benchMarking.id)
print(baUser?.thresholdTransactionReporting.total)
记得用.useDefaultKeys
.convertFromSnakeCase