Lets consider you have a sample JSON as shown below
https://gist.github.com/kmdarshan/cfa6a940268f7091faf886ed63b3b559
You can make use of Codable Library (https://developer.apple.com/documentation/swift/codable) in Swift to read and write data from a JSON.
Firstly you need to map your data from the JSON onto a Struct as shown below. Once you have done that, its easy to read it using the decode and encode libraries in swift.
https://gist.github.com/kmdarshan/897f3e54ab4f133c25af4512be7e4ff1
Let’s consider you have the below JSON.
[
{
"name": "red",
"loan_amount": 1234
},
{
"name": "flower",
"loan_amount": 100
},
{
"name": "Inc",
"loan_amount": "100"
}
]
It’s an array. Everything seems fine, until you notice that the loan_amount is a String and Int. This will fail to parse normally. You would need to go about this by parsing the individual key in the initializer as show below
struct StudentInfo : Codable {
var name: String = ""
var amount: Int = 0
enum CodingKeys: String, CodingKey {
case name
case amount = "loan_amount"
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
name = try container.decode(String.self, forKey: .name)
do {
// first try to parse as a Int
amount = try container.decode(Int.self, forKey: .amount)
} catch {
// Int parsing failed, lets parse it as a String
let amountString = try container.decode(String.self, forKey: .amount)
if let amountInt = Int(amountString) {
amount = amountInt
} else {
throw error
}
}
}
}
[learnjson.StudentInfo(name: "red", amount: 1234), learnjson.StudentInfo(name: "flower", amount: 100), learnjson.StudentInfo(name: "Inc", amount: 100)]
You will get the output as shown above.
Now let’s add more complication to the JSON. Let’s add a dictionary inside a dictionary. And add an array inside the dictionary.
[
{
"name": "red",
"loan_amount": 1234,
"address" : {
"street": "175 bay",
"zip": 95134
},
"surnames": [
"jagan",
"hello",
"dimmmer"
]
},
{
"name": "flower",
"loan_amount": 100
},
{
"name": "Inc",
"loan_amount": "100",
"address" : {
"street": "175 bay",
"zip": 95134
}
}
]
You need to change the parsing in the decoder. First, you would need to create another codable called Address and then pass this to the StudentInfo codable struct. Then parse it in the init method.
struct Address: Codable {
var street: String
var zip: Int
}
struct StudentInfo : Codable {
var name: String = ""
var amount: Int = 0
var address: Address
var surnames: [String] = []
enum CodingKeys: String, CodingKey {
case name
case amount = "loan_amount"
case address
case surnames
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
name = try container.decode(String.self, forKey: .name)
do {
// first try to parse as a Int
amount = try container.decode(Int.self, forKey: .amount)
} catch {
// Int parsing failed, lets parse it as a String
let amountString = try container.decode(String.self, forKey: .amount)
if let amountInt = Int(amountString) {
amount = amountInt
} else {
throw error
}
}
do {
address = try container.decode(Address.self, forKey: .address)
} catch {
address = Address(street: "", zip: 0)
}
do {
surnames = try container.decode([String].self, forKey: .surnames)
} catch {
surnames = []
}
}
}
The output would be as shown below
[learnjson.StudentInfo(name: "red", amount: 1234, address: learnjson.Address(street: "175 bay", zip: 95134), surnames: ["jagan", "hello", "dimmmer"]), learnjson.StudentInfo(name: "flower", amount: 100, address: learnjson.Address(street: "", zip: 0), surnames: []), learnjson.StudentInfo(name: "Inc", amount: 100, address: learnjson.Address(street: "175 bay", zip: 95134), surnames: [])]
Leave a Reply