Reputation: 123
I am new to swift and am trying to figureout passing Nested Json. So far I have tried JSONSerialization without success but after being advised to switch to Codable I have give it a try but I keep getting nill from parsed JSON. Code I have so far:
struct AppData: Codable {
let paymentMethods: [PaymentMethods]?
}
struct PaymentMethods: Codable {
let payment_method: String?
}
AF.request(startAppUrl, method: .post, parameters: requestParams , encoding: JSONEncoding.default).responseString{
response in
switch response.result {
case .success(let data):
let dataStr = data.data(using: .utf8)!
let parsedResult = try? JSONDecoder().decode( AppData.self, from: dataStr)
print(parsedResult)
case .failure(let error):
print((error.localizedDescription))
}
}
My JSON data can be found here: https://startv.co.tz/startvott/engine/jsonsample/ . I am using xcode 11
I will appreciate assistance as its already one week stuck on this.
Upvotes: 0
Views: 308
Reputation: 285260
First of all replace responseString
with responseData
in the request line, this avoids the extra step to convert string (back) to data.
Second of all add always a do - catch
block around a JSONDecoder
line. Never ignore decoding errors with try?
. The block will catch this comprehensive DecodingError
:
typeMismatch(Swift.Array, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "paymentMethods", intValue: nil)], debugDescription: "Expected to decode Array but found a string/data instead.", underlyingError: nil))
The error states that the value for key paymentMethods
is not an array. It's a string. Looking at the JSON it's in fact a nested JSON string which must be decoded on a second level.
struct AppData: Codable {
let paymentMethods: String
}
struct PaymentMethods: Codable {
let paymentMethod: String
}
AF.request(startAppUrl, method: .post, parameters: requestParams , encoding: JSONEncoding.default).responseData{
response in
switch response.result {
case .success(let data):
do {
let parsedResult = try JSONDecoder().decode( AppData.self, from: data)
let paymentData = Data(parsedResult.paymentMethods.utf8)
let secondDecoder = JSONDecoder()
secondDecoder.keyDecodingStrategy = .convertFromSnakeCase
let paymentMethods = try secondDecoder.decode([PaymentMethods].self, from: paymentData)
print(paymentMethods)
} catch {
print(error)
}
case .failure(let error):
print((error.localizedDescription))
}
}
Side note:
The URL doesn't require a POST request and parameters. You can omit all parameters except the first.
Upvotes: 2