0

I have the json in below structure

{
    "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
}

and my codable class look like below

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

I am able get the first level keys

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)

i get the first level keys like ["admin","vinoth59","ba_user"]. I need to get the second level keys ["CUSTOMER_PROFILING","RISK_ASSESSMENT",.....]. how to achieve using this codable

9
  • @JoakimDanielson I am using quicktype.io only. its only generate the above codable strucrure Commented May 15, 2020 at 7:55
  • Use dec.keyDecodingStrategy = .useDefaultKeys instead of dec.keyDecodingStrategy = . convertFromSnakeCase Commented May 15, 2020 at 8:03
  • @udbhateja if i change that how can access the second level keys Commented May 15, 2020 at 8:08
  • I removed all custom init methods and used a vanilla decoder JSONDecoder().decode(UserRiskReportBase.self, from: data) and I can access the values Commented May 15, 2020 at 8:10
  • @Ben10 You have added default keys for second level objects, this will work fine. I just checked this and the output is fine. Go ahead and try. Commented May 15, 2020 at 8:10

2 Answers 2

2

The below works for me, note that I have done some simplifications and removed not needed code like init(from:) and I also removed Optional for a lot of properties

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 {$0.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)
}
Sign up to request clarification or add additional context in comments.

4 Comments

using this method how can form ["CUSTOMER_PROFILING","RISK_ASSESSMENT","LINK_ANALYSIS".....]
You only want the keys?
Yes I want only the keys in array
UserRiskReport.CodingKeys.allCases.map({$0.rawValue}) but you first must make CodingKeys conform to CaseIterable
1
    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)

Remember replacing .convertFromSnakeCase with .useDefaultKeys

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.