Assume you have the following json. If you notice carefully, the data is almost similar to each other. Our goal is to give us a single data structure, which will store the details shown here.
var deposit = """
{
"channelName": "Deposit",
"withdrawableBalance": 1000,
"accounts": [
{
"accountId": "122xeeweX",
"bank": "wells fargo",
"withdrawableBalance": 1000
}
]
}
"""
var withdraw = """
{
"channelName": "Withdraw",
"accounts": [
{
"accountId": "122xeeweX",
"bank": "wells fargo",
"withdrawableBalance": 1000
},
{
"accountId": "12wwwewWWxeeweX",
"bank": "WIRE",
"withdrawableBalance": 1000,
"createdDate": 1663727163000
}
]
}
"""
var buy = """
{
"channelName": "Buy",
"buyLimit": 1000,
"minimumBuyAmount": 10,
"accounts": [
{
"accountId": "122xeeweX",
"bank": "wells fargo",
"buy": 1000
}
]
}
"""
To begin with, let’s define a protocol
protocol Transaction {
var channelName: String { get }
}
Let’s define the Codable object for these responses. You can easily convert the string into a Codable object using the tool here https://app.quicktype.io/
// MARK: - Deposit
struct Deposit: Codable, Transaction {
let channelName: String
let withdrawableBalance: Int?
let accounts: [Account]?
}
// MARK: - Account
struct Account: Codable {
let accountID, bank: String?
let withdrawableBalance: Int?
enum CodingKeys: String, CodingKey {
case accountID = "accountId"
case bank, withdrawableBalance
}
}
// MARK: - Buy
struct Buy: Codable, Transaction {
let channelName: String
let buyLimit, minimumBuyAmount: Int?
let accounts: [BuyAccount]?
}
// MARK: - Account
struct BuyAccount: Codable {
let accountID, bank: String
let buy: Int?
enum CodingKeys: String, CodingKey {
case accountID = "accountId"
case bank, buy
}
}
// MARK: - Withdraw
struct Withdraw: Codable, Transaction {
let channelName: String
let accounts: [WithdrawAccount]?
}
// MARK: - Account
struct WithdrawAccount: Codable {
let accountID, bank: String?
let withdrawableBalance, createdDate: Int?
enum CodingKeys: String, CodingKey {
case accountID = "accountId"
case bank, withdrawableBalance, createdDate
}
}
Now let’s define the actual method to decode this json. You can notice we have a single return type called Transaction.
struct ResponseDecoder {
func decode(_ response: String, for intent: Int) -> Transaction? {
do {
let jsonData = response.data(using: .utf8)!
let jsonDecoder = JSONDecoder()
var transaction: Transaction
switch intent {
case 0:
transaction = try jsonDecoder.decode(Withdraw.self, from: jsonData)
return transaction
case 1:
return try jsonDecoder.decode(Buy.self, from: jsonData)
case 2:
return try jsonDecoder.decode(Deposit.self, from: jsonData)
default:
return nil
}
} catch {
print("error decoding string")
}
return nil
}
}
Display the data as shown below
struct DisplayAllData {
func display() {
guard let withdrawResponse = ResponseDecoder().decode(withdraw, for: 0) else {
return
}
print(withdrawResponse.channelName)
guard let buyResponse = ResponseDecoder().decode(buy, for: 1) else {
return
}
print(buyResponse.channelName)
guard let depositResponse = ResponseDecoder().decode(deposit, for: 2) else {
return
}
print(depositResponse.channelName)
}
}
DisplayAllData().display()
Leave a Reply