decoding a nested array in swift 4
If you want to take advantage of JSONDecoder
you have to create a nested struct(ure).
I recommend to use the name Root
for the root object and put the child struct into Root
struct Root : Decodable {
struct User : Decodable {
let id: Int
let name: String
}
let users : [User]
}
let json = """
{
"users": [{"id": 1, "name":"John Doe"},
{"id": 2, "name":"Luke Smith"}]
}
"""
let data = Data(json.utf8)
do {
let root = try JSONDecoder().decode(Root.self, from: data)
print(root.users)
} catch {
print(error)
}
No Data when Decoding Nested Array in Json by Swift
This code is enough:
struct PriceList: Decodable {
let success: Bool
let message: String
let response: [ResponseList]
enum CodingKeys: String, CodingKey {
case success = "IsSuccess"
case message = "Message"
case response = "ResponseData"
}
}
struct ResponseList: Decodable {
let packageID: Int
let packageName: String
let price, discountedPrice: Double
let type: String
let testPackageGroupID: Int?
let sampleType: [SampleTypeList]?
enum CodingKeys: String, CodingKey {
case packageID = "PackageId"
case packageName = "PackageName"
case price = "Price"
case discountedPrice = "DiscountedPrice"
case type = "Type"
case testPackageGroupID = "TestPackageGroupId"
case sampleType = "SampleTypeList"
}
}
struct SampleTypeList: Decodable {
let testSampleTypeID: String
let sampleName: String
let colourCode: String
enum CodingKeys: String, CodingKey {
case testSampleTypeID = "TestSampleTypeId"
case sampleName = "SampleName"
case colourCode = "ColourCode"
}
}
What I did fix, what I didn't like from your sample code:
- Please name your variables starting with a lowercase, it's convention, and is easier to read (if everyone follow the same convention/standards).
- Make your code compilable for us. It's not that hard, but if anyone would want to help you, it be much easier for us to just copy/paste your code and test it and not fix everything in it. You'll have better chances to get an answer. There is a
Cannot assign value of type 'String' to type 'Int'
becausepackageID
is set as an Int and trying to be decoded as a String, there are missing spaces:variable=
instead ofvariable =
, etc. It's annoying to have us to fix that to be able to work. - You printed the JSON, that's a good point, to test it, there is no need anymore of the Web API Call, see following sample
- You said that some values can be null, so please provide a JSON with these sample, cut if needed, see the JSON I used as sample, I checked on a JSON online validator that is was valid, and that's all. Since you that that 2 values could be null, I used all possibilities: one with none null, one with one null, one with the other null, and one with both null. Then, for each of these, I put the values as optional.
- I removed all the
init(from decoder:)
as they are useless. If you decode each value withlet container = try decoder.container(keyedBy:CodingKeys.self); variable = try container.decode(VariableType.self,forKey: .correspondingCodingKeyInTheEnumCase)
, that code is already done internally by Apple when compiling.
With sample test:
let jsonStr = """
{
"IsSuccess": true,
"Message": "Data Returned",
"ResponseData": [{
"PackageId": 1025,
"PackageName": "17 OH Progesterone",
"Price": 0.00,
"DiscountedPrice": 1.0,
"Type": "Test",
"TestPackageGroupId": 3,
"SampleTypeList": [{
"TestSampleTypeId": "50",
"SampleName": "Serum",
"ColourCode": "#FFB500"
}]
},
{
"PackageId": 1916,
"PackageName": "24 hour Albumin creatinine ratio (ACR)",
"Price": 120.00,
"DiscountedPrice": 1.0,
"Type": "Test",
"TestPackageGroupId": 3,
"SampleTypeList": null
},
{
"PackageId": 1914,
"PackageName": "24 Hour Microalbumin Creatinine Ratio",
"Price": 110.00,
"DiscountedPrice": 1.0,
"Type": "Test",
"TestPackageGroupId": null,
"SampleTypeList": [{
"TestSampleTypeId": "66",
"SampleName": "24 hrs Urine",
"ColourCode": "#212DC1"
}]
},
{
"PackageId": 1913,
"PackageName": "24 Hours Protein Creatinine Ratio (PCR) ",
"Price": 12.00,
"DiscountedPrice": 1.0,
"Type": "Test",
"TestPackageGroupId": null,
"SampleTypeList": null
}
]
}
"""
do {
let priceList = try JSONDecoder().decode(PriceList.self, from: Data(jsonStr.utf8))
print(priceList)
} catch {
print("Error while decoding: \(error)")
}
How to decode a dictionary with a nested array inside?
Change the type of searchResults from [String: AnyObject] to 'SearchResults'
var searchResults : SearchResults?
JSON decoding double nested array in Swift
Where do you decode the days
key? That's the problem. You need an intermediate struct
struct Root : Decodable {
let itenaries : Itenary
}
struct Itenary : Decodable {
let days : [[Days]]
}
...
let result = try decoder.decode(Root.self, from: fileData)
print(result.iternaries.days[0][0].itenary_id)
Swift 4 Decodable: struct from nested array
You can use nestedContainer(keyedBy:) and nestedUnkeyedContainer(forKey:) for decoding nested array and dictionary like this to turn it into your desired structure. Your decoding in init(decoder: ) might look something like this,
Actor extension for decoding,
extension Actor: Decodable {
enum CodingKeys: CodingKey { case id, name }
enum ActorKey: CodingKey { case actor }
init(from decoder: Decoder) throws {
let rootKeys = try decoder.container(keyedBy: ActorKey.self)
let actorContainer = try rootKeys.nestedContainer(keyedBy: CodingKeys.self,
forKey: .actor)
try id = actorContainer.decode(Int.self,
forKey: .id)
try name = actorContainer.decode(String.self,
forKey: .name)
}
}
PlaceholderData extension for decoding,
extension PlaceholderData: Decodable {
enum CodingKeys: CodingKey { case filmCount, year, category, actors }
enum NodeKeys: CodingKey { case nodes }
init(from decoder: Decoder) throws {
let rootContainer = try decoder.container(keyedBy: CodingKeys.self)
try filmCount = rootContainer.decode(Int.self,
forKey: .filmCount)
try year = rootContainer.decode(Int.self,
forKey: .year)
try category = rootContainer.decode(String.self,
forKey: .category)
let actorsNode = try rootContainer.nestedContainer(keyedBy: NodeKeys.self,
forKey: .actors)
var nodes = try actorsNode.nestedUnkeyedContainer(forKey: .nodes)
var allActors: [Actor] = []
while !nodes.isAtEnd {
let actor = try nodes.decode(Actor.self)
allActors += [actor]
}
actors = allActors
}
}
Then, you can decode it like this,
let decoder = JSONDecoder()
do {
let placeholder = try decoder.decode(PlaceholderData.self, from: jsonData)
print(placeholder)
} catch {
print(error)
}
Here, the basic idea is to decode dictionary container using nestedContainer(keyedBy:) and array container using nestedUnkeyedContainer(forKey:)
How to decode nested JSON array and object with JSONDecoder in swift 4.1 and xcode 9.3?
OrderDetials
is Array of Dictionary
[[String: String?]]
, and your Initial
response is Dictionary also order_details
is Wrong json String
not Dictionary
, so we will parse it as string , in Codable
every dictionary {}
is converted t Struct
or Class
and []
is Array
Model:
import Foundation
struct Initial: Codable {
let orderDetials: [OrderDetial]
enum CodingKeys: String, CodingKey {
case orderDetials = "OrderDetials"
}
}
struct OrderDetial: Codable {
let orderID, orderRefNumber, custMob, storeName: String
let storeID, orderDetails, orderAmount, orderStatus: String
let orderStatusRemark, orderPlaceAt: String
let orderStatusShangeAt:String?
enum CodingKeys: String, CodingKey {
case orderID = "order_id"
case orderRefNumber = "order_ref_number"
case custMob = "cust_mob"
case storeName = "store_name"
case storeID = "store_id"
case orderDetails = "order_details"
case orderAmount = "order_amount"
case orderStatus = "order_status"
case orderStatusRemark = "order_status_remark"
case orderPlaceAt = "order_place_at"
case orderStatusShangeAt = "order_status_change_at"
}
}
// MARK: Convenience initializers
extension Initial {
init(data: Data) throws {
self = try JSONDecoder().decode(Initial.self, from: data)
}
}
Used Like this :
if let initial = try? Initial.init(data: data){
for item in initial.orderDetials {
print(item.orderAmount)
print(item.orderDetails) // here is Wrong format from your Server API
}
}
Order_details is wrong
{'allorder':[{"date_time":"","item":"2","name":"CHICKN ROLL","price":"360"}]}{"TaxDetials":[{"tax_per":"5","tax_name":"CGST & SGST"}]}
Related Topics
Missing Required Module Firebase - Jenkins Build Error
How to Get .Adjustsfontsizetofitwidth to Function Properly
Why Would One Use Nested Classes
How to Create a Cocoapod with .Swift
Macos Security Scoped Url Bookmark for Folder
Why Is Swift Counting This Grapheme Cluster as Two Characters Instead of One
How to Specify Japanese Encoding for a UIlabel
How to Decode a Utf16 String into a Unicode Character
Accessing Bundle of Main Application While Running Xctests
Loading Image from Assets to Nsimage Keep Getting Error, Expecting Nsimage.Name
How to Byte Reverse Nsdata Output in Swift The Littleendian Way
How to Test If an Instance Is a Specific Class or Type in Swift
Difference Between Object(Forkey:) and Value(Forkey:) in Userdefaults
Bundle.Main.Path(Forresource... Always Returns Nil When Looking for Xml File