Swift Large Data File Into Struct (JSON or CSV) - json
I've got a huge amount of data (80 columns over 60k rows). It's created in Excel and exported to CSV. The CSV file is 9.4mb. I then converted the CSV to JSON and it became 94.5mb. Obviously I can't have a 100mb data file included with the app so I tried thinking of different solutions.
I used the CSV itself and parsed it out into a struct. However, because the CSV has commas within some of the data (surrounded by double quotes of course), it isn't parsing correctly.
I could reformat the JSON to have the headers in one array and the data in another which would solve my comma issue, but I haven't found an up-to-date real-world solution to doing this.
This is medical drug data so some of the names can be quite long/complex, and a lot of rows have blank values for various fields simply because there is no corresponding data for that entry.
Here's a small example of the CSV formatted data:
medID,type,nameLong,isCurrent,nameShort,isCompound,strength,mUnit,strengthPer,mUnitPer,strengthIn,mUnitIn,ing1,ing1Strength,ing1MUnit,ing2,ing2Strength,ing2MUnit,ing3,ing3Strength,ing3MUnit,ing4,ing4Strength,ing4MUnit,ing5,ing5Strength,ing5MUnit,ing6,ing6Strength,ing6MUnit,ing7,ing7Strength,ing7MUnit,ing8,ing8Strength,ing8MUnit,ing9,ing9Strength,ing9MUnit,ing10,ing10Strength,ing10MUnit,ing11,ing11Strength,ing11MUnit,ing12,ing12Strength,ing12MUnit,ing13,ing13Strength,ing13MUnit,ing14,ing14Strength,ing14MUnit,ing15,ing15Strength,ing15MUnit,ing16,ing16Strength,ing16MUnit,ing17,ing17Strength,ing17MUnit,ing18,ing18Strength,ing18MUnit,ing19,ing19Strength,ing19MUnit,ing20,ing20Strength,ing20MUnit,ing21,ing21Strength,ing21MUnit,ing22,ing22Strength,ing22MUnit,ing23,ing23Strength,ing23MUnit
123456,Inhalant,"Fluticasone Propionate/Salmeterol 500/50 mcg/INHAL Dry Powder Inhaler, 14 Blisters, Inhalant",N,,TRUE,,,,,,,Fluticasone Propionate,500,mcg/INHAL,Salmeterol,50,mcg/INHAL,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
234567,Inhalant,"Advair Diskus 500/50 mcg/INHAL Dry Powder Inhaler, 14 Blisters, Inhalant",N,Advair Diskus,TRUE,,,,,,,Fluticasone Propionate,500,mcg/INHAL,Salmeterol,50,mcg/INHAL,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
345678,Powder,"Fluticasone Propionate 500 mcg / Salmeterol 50 mcg (Salmeterol Xinafoate 72.5 mcg) Per Actuat Dry Powder Inhaler, 28 Actuat",O,,TRUE,,,,,,,Fluticasone Propionate,500,mcg,Salmeterol,50,mcg,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
456789,Powder,"Advair Diskus 500/50 (Fluticasone Propionate 0.5 mg/ACTUAT / Salmeterol 0.05 mg/ACTUAT) Dry Powder Inhaler, 28 Actuat",O,,TRUE,,,,,,,Fluticasone Propionate,0.5,mg/ACTUAT,Salmeterol,0.05,mg/ACTUAT,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
567890,Inhalant,"Fluticasone Propionate/Salmeterol 500/50 mcg/INHAL Dry Powder Inhaler, 60 Blisters, Inhalant",N,,TRUE,,,,,,,Fluticasone Propionate,500,mcg/INHAL,Salmeterol,50,mcg/INHAL,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
678901,Inhalant,"Advair Diskus 500/50 mcg/INHAL Dry Powder Inhaler, 60 Blisters, Inhalant",N,Advair Diskus,TRUE,,,,,,,Fluticasone Propionate,500,mcg/INHAL,Salmeterol,50,mcg/INHAL,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
What I need is a solution to getting all of this data into the app so it can be accessed in the fastest manner. As it will only be used in one section of the app, I wasn't sure if putting it all in CoreData was a good idea (plus, it will be constantly updated), and instead thought it best to load it where it's needed and then unload it once the user leaves that section of the app, thus freeing up memory. However, I'm open to the best solution.
This is where I'm at right now with parsing the CSV file directly (and it works, sort of).
struct DrugsList: Codable, Hashable {
let medID: String
let type: String
let nameLong: String
let isCurrent: String
let nameShort: String?
let isCompound: String
let strength: String?
let mUnit: String?
let strengthPer: String?
let mUnitPer: String?
let strengthIn: String?
let mUnitIn: String?
let ing1: String?
let ing1Strength: String?
let ing1MUnit: String?
let ing2: String?
let ing2Strength: String?
let ing2MUnit: String?
let ing3: String?
let ing3Strength: String?
let ing3MUnit: String?
let ing4: String?
let ing4Strength: String?
let ing4MUnit: String?
let ing5: String?
let ing5Strength: String?
let ing5MUnit: String?
let ing6: String?
let ing6Strength: String?
let ing6MUnit: String?
let ing7: String?
let ing7Strength: String?
let ing7MUnit: String?
let ing8: String?
let ing8Strength: String?
let ing8MUnit: String?
let ing9: String?
let ing9Strength: String?
let ing9MUnit: String?
let ing10: String?
let ing10Strength: String?
let ing10MUnit: String?
let ing11: String?
let ing11Strength: String?
let ing11MUnit: String?
let ing12: String?
let ing12Strength: String?
let ing12MUnit: String?
let ing13: String?
let ing13Strength: String?
let ing13MUnit: String?
let ing14: String?
let ing14Strength: String?
let ing14MUnit: String?
let ing15: String?
let ing15Strength: String?
let ing15MUnit: String?
let ing16: String?
let ing16Strength: String?
let ing16MUnit: String?
let ing17: String?
let ing17Strength: String?
let ing17MUnit: String?
let ing18: String?
let ing18Strength: String?
let ing18MUnit: String?
let ing19: String?
let ing19Strength: String?
let ing19MUnit: String?
let ing20: String?
let ing20Strength: String?
let ing20MUnit: String?
let ing21: String?
let ing21Strength: String?
let ing21MUnit: String?
let ing22: String?
let ing22Strength: String?
let ing22MUnit: String?
let ing23: String?
let ing23Strength: String?
let ing23MUnit: String?
init(raw: [String]) {
medID = raw[0]
type = raw[1]
nameLong = raw[2]
isCurrent = raw[3]
nameShort = raw[4]
isCompound = raw[5]
strength = raw[6]
mUnit = raw[7]
strengthPer = raw[8]
mUnitPer = raw[9]
strengthIn = raw[10]
mUnitIn = raw[11]
ing1 = raw[12]
ing1Strength = raw[13]
ing1MUnit = raw[14]
ing2 = raw[15]
ing2Strength = raw[16]
ing2MUnit = raw[17]
ing3 = raw[18]
ing3Strength = raw[19]
ing3MUnit = raw[20]
ing4 = raw[21]
ing4Strength = raw[22]
ing4MUnit = raw[23]
ing5 = raw[24]
ing5Strength = raw[25]
ing5MUnit = raw[26]
ing6 = raw[27]
ing6Strength = raw[28]
ing6MUnit = raw[29]
ing7 = raw[30]
ing7Strength = raw[31]
ing7MUnit = raw[32]
ing8 = raw[33]
ing8Strength = raw[34]
ing8MUnit = raw[35]
ing9 = raw[36]
ing9Strength = raw[37]
ing9MUnit = raw[38]
ing10 = raw[39]
ing10Strength = raw[40]
ing10MUnit = raw[41]
ing11 = raw[42]
ing11Strength = raw[43]
ing11MUnit = raw[44]
ing12 = raw[45]
ing12Strength = raw[46]
ing12MUnit = raw[47]
ing13 = raw[48]
ing13Strength = raw[49]
ing13MUnit = raw[50]
ing14 = raw[51]
ing14Strength = raw[52]
ing14MUnit = raw[53]
ing15 = raw[54]
ing15Strength = raw[55]
ing15MUnit = raw[56]
ing16 = raw[57]
ing16Strength = raw[58]
ing16MUnit = raw[59]
ing17 = raw[60]
ing17Strength = raw[61]
ing17MUnit = raw[62]
ing18 = raw[63]
ing18Strength = raw[64]
ing18MUnit = raw[65]
ing19 = raw[66]
ing19Strength = raw[67]
ing19MUnit = raw[68]
ing20 = raw[69]
ing20Strength = raw[70]
ing20MUnit = raw[71]
ing21 = raw[72]
ing21Strength = raw[73]
ing21MUnit = raw[74]
ing22 = raw[75]
ing22Strength = raw[76]
ing22MUnit = raw[77]
ing23 = raw[78]
ing23Strength = raw[79]
ing23MUnit = raw[80]
}
}
func loadDrugsCSV(from fileName: String) -> [DrugsList] {
var csvToStruct = [DrugsList]()
// Locate the CSV File
guard let filePath = Bundle.main.path(forResource: fileName, ofType: "csv") else {
return []
}
// Convert the contents of the CSV file into one long string
var data = ""
do {
data = try String(contentsOfFile: filePath)
} catch {
print(error)
return []
}
// Split the long string into an array of rows
// Detect carriage returns "\n", then split
var rows = data.components(separatedBy: "\n")
// Remove header rows
rows.removeFirst()
// Loop through each row and split
for row in rows {
let csvColumns = row.components(separatedBy: ",")
let drugStruct = DrugsList.init(raw: csvColumns)
csvToStruct.append(drugStruct)
}
return csvToStruct
}
Related
Is there a better way to decode JSON data that has a repeating variable with different counts?
For example, say there is an API which returns JSON with the following keys. Sometimes the keys can have one ingredient or twenty. Is there a better way than listing all the possible outcomes in my model? Can I set this up programmatically? let strIngredient1: String? let strIngredient2: String? let strIngredient3: String? let strIngredient4: String? let strIngredient5: String? let strIngredient6: String? let strIngredient7: String? let strIngredient8: String? let strIngredient9: String? let strIngredient10: String? let strIngredient11: String? let strIngredient12: String? let strIngredient13: String? let strIngredient14: String? let strIngredient15: String? let strIngredient16: String? let strIngredient17: String? let strIngredient18: String? let strIngredient19: String? let strIngredient20: String? I am referring to this API's json data: https://www.themealdb.com/api/json/v1/1/lookup.php?i=53049
One possible solution: struct RawCodingKey: CodingKey { let stringValue: String let intValue: Int? init(stringValue: String) { self.stringValue = stringValue intValue = nil } init(intValue: Int) { stringValue = "\(intValue)" self.intValue = intValue } } ... let container = try decoder.container(keyedBy: RawCodingKey.self) let ingredients = try 1...20.map { index in try container.decodeIfPresent(String.self, forKey: RawCodingKey(stringValue: "strIngredient\(index)")) } You might want to add compactMap, trimming spaces and filtering empty strings to remove invalid items.
Store TMDB API data
I'm working on an app that requires the use of the TMDB API. I have been trying to store the results from the API in a struct but it keeps giving me the error: No exact matches in call to subscript This is the struct: struct MovieList: Codable { let dates: Date? let page: Int? let results: [Result]? let total_pages: Int? let total_results: Int? } struct Result: Codable { let adult: Bool? let backdrop_path: String? let genre_ids: [Int]? let id: Int? let original_language: String? let original_title: String? let overview: String? let popularity: Int? let poster_path: String? let release_date: String? let title: String? let video: Bool? let vote_average: Float? let vote_count: Int? And here is my API call: public class LoadTMDBData { var tmdbMoviesData = [[Result]]() init() { getTMDBData() } func getTMDBData() { guard let url = URL(string: "") else { fatalError("Invalid URL") } // Set session configuration to default let config = URLSessionConfiguration.default let session = URLSession(configuration: config) let task = session.dataTask(with: url) { data, response, error in // Check that data has been returned guard let data = data else { return } do { let tmdbData = try JSONDecoder().decode([MovieList].self, from: data) self.tmdbMoviesData = tmdbData["result"] } catch{ let error = error print(error.localizedDescription) } } // execute the HTTP request task.resume() }
When using a struct you don't access its properties using a string key like ["someProperty"], instead you use dot notation .someProperty, so to get the results property you do let results = myMoveList.results What makes it a little more complicated here is that you have, as you properly have coded for, an array of MovieList and that you want to extract all results into an array for array. For this you can use a high order function map to do this self.tmdbMoviesData = tmdbData.map(\.results) but since results is optional we use a similar function that will filter out any nil values, compactMap self.tmdbMoviesData = tmdbData.compactMap(\.results) Another comment, you have made all properties optional in your structs and while this is an easy way forward it might lead to hiding some decoding issues and more cumbersome code when using the types. I would recommend not to use optional unless really needed.
How to decode this using JSONDecoder and Swift 4 Decodabale class
I have decoded this using JSONSerialization. But for my own knowledge and the maintenance of my code. I would like to know how to decode this. This is what I have so far: let urlString = "site deleted" + "/DataSource/Mobile/?Action=MyProfile&uid=" + uid + "&uuid=" + uuid guard let url = URL(string: urlString) else {return} URLSession.shared.dataTask(with: url) { (data, _, error) in if let err = error { print("Handle MyProfileJSON error: ", err) } guard let data = data else {return} do { // swift 4.2 but we cant use it right now let profile = try JSONDecoder().decode(RequestResult.self, from: data) print(profile) completion(profile) } catch let err { print("Handle Decoder Error: ", err) } }.resume() I'm not too worried about the cases but this is what I have so far. I know the case I use is not the convention, that's why I did this with JSONSerialization so I can use camelCase. If you can help me convert it to camelCase too that would be amazing but my focus is to Decode this using Decodable class. Thanks a lot, guys. And this are my structs: struct RequestResult: Decodable { var Action: String? var Params: [String: String]? var DATA: [String: String]? } struct Params: Decodable { var Action_get: String? var uid_get: String? } struct DATA: Decodable { var Id: String? var UserCode: String? var HomePhone: String? var Mobile: String? var WorkPhone: String? var Email: String? var AltEmail: String? var UnitNo: String? var StreetNo: String? var StreetName: String? var City: String? var StateProvince: String? var Country: String? var ZipPostalCode: String? }
The structure of the JSON is very clear The root object RequestResult contains a string and two dictionaries. The dictionaries are replaced by structs. The CodingKeys are useful to rename the keys to more meaningful and naming convention conforming names. The left side of an enum case is the struct member name, the right side the original JSON key. A struct member name must match the dictionary key (or the mapped CodingKey). The struct names are arbitrary. All struct members can be declared as constants (let) and as non-optional if the JSON contain always the keys. struct RequestResult: Decodable { private enum CodingKeys : String, CodingKey { case action = "Action", params = "Params", data = "DATA" } let action: String let params: Parameter let data: UserData } The dictionary for key Params will be renamed to Parameter and DATA to UserData struct Parameter: Decodable { private enum CodingKeys : String, CodingKey { case action = "Action_get", uid = "uid_get" } let action: String let get: String } struct UserData: Decodable { private enum CodingKeys : String, CodingKey { case id = "Id", userCode = "UserCode", homePhone = "HomePhone" case mobile = "Mobile", workPhone = "WorkPhone", email = "Email" case altEmail = "AltEmail", unitNo = "UnitNo", streetNo = "StreetNo" case streetName = "StreetName", city = "City", stateProvince = "StateProvince" case country = "Country", zipPostalCode = "ZipPostalCode" } let id: String, userCode, homePhone, mobile: String let workPhone, email, altEmail, unitNo: String let streetNo, streetName, city, stateProvince: String let country, zipPostalCode: String }
Swift 4.1 JSON to Struct then to array of distinct dates
I am calling an API that returns a JSON result of appointments. Example: [{"DiarySummary":"Test appointment","DiaryDescription":"Test","DiaryId":"62","EventNo":"","EventTypeId":"","StartDateTime":"07/06/2018 09:00:51","StopDateTime":"07/06/2018 21:00:51","DayHalfDay":"0","AgentGroupName":"DEV","AgentInitials":"AC","AgentId":"5","OwnerShortName":"","OwnerLongName":"","AbsenceTypeDescription":"Working From Home","AbsenceTypeId":"15"}... I have this mapping to a struct in my code using the decode function: struct DiaryAppointment: Decodable { let DiarySummary: String? let DiaryDescription: String? let DiaryId: String? let EventNo: String? let EventTypeId: String? let StartDateTime: String? let StopDateTime: String? let DayHalfDay: String? let AgentGroupName: String? let AgentInitials: String? let AgentId: String? let OwnerShortName: String? let OwnerLongName: String? let AbsenceTypeDescription: String? let AbsenceTypeId: String? } self.appointments = try JSONDecoder().decode([DiaryAppointment].self, from: data!) and then the self.appointments array is being used in a UICollectionView. All of this works absolutely fine. However, I would like to split the collectionView into sections based on distinct StartDates with a header fro each. I have tried creating a secondary array, but the value of StartDateTime in my JSON and therefore in my appointments array is a string as opposed to a date. I can loop through the appointments array and convert the value of appointment.StartDateTime to a date object and add to a new array which should allow me to pick out distinct dates, but I won't be able to split the original appointments array because the value is still a string. Is it possible convert this to a date object at the point off calling decode? If not, how can I achieve the required functionality, or, is there a better way to do this?
First of all use CodingKeys to get lowercased variable names and declare the properties as much non-optional as possible: struct DiaryAppointment: Decodable { private enum CodingKeys: String, CodingKey { case diarySummary = "DiarySummary", diaryDescription = "DiaryDescription", diaryId = "DiaryId" case eventNo = "EventNo", eventTypeId = "EventTypeId", startDateTime = "StartDateTime" case stopDateTime = "StopDateTime", dayHalfDay = "DayHalfDay", agentGroupName = "AgentGroupName" case agentInitials = "AgentInitials", agentId = "AgentId", ownerShortName = "OwnerShortName" case ownerLongName = "OwnerLongName", absenceTypeDescription = "AbsenceTypeDescription", absenceTypeId = "AbsenceTypeId" } let diarySummary, diaryDescription, diaryId, eventNo, eventTypeId: String let startDateTime, stopDateTime: Date let dayHalfDay, agentGroupName, agentInitials, agentId: String let ownerShortName, ownerLongName, absenceTypeDescription, absenceTypeId: String } Declare startDateTime and stopDateTime as Date and pass a DateFormatter as dateDecodingStrategy let decoder = JSONDecoder() let dateFormatter = DateFormatter() dateFormatter.locale = Locale(identifier: "en_US_POSIX") dateFormatter.dateFormat = "dd/MM/yyyy HH:mm:ss" decoder.dateDecodingStrategy = .formatted(dateFormatter)
Fetching data using swift 4
I'm trying to fetch data from swift 4 and I'm having nil as response. 1- I have this piece of code and I have the error "Type 'JobSeekerDataAPI' does not conform to protocol 'Decodable' import UIKit import SwiftyJSON struct JobSeekerDataAPI : Decodable { let job_seeker_id: String? let job_seeker_name: String? let linkedin_id: String? let first_name: String? let last_name: String? let user_id: String? let profile_pic_file: String? let personal_job_title: String? let about: String? let interest: String? let most_recent_work_history_id: String? let most_recent_education_id: String? let rel_work_exp_year: String? let most_recent_salary: String? let salary_expectation_high: String? let salary_expectation_low: String? let is_salary_on_public_profile: String? let education_level_id: String? let location_country_id: String? let location_timezone_id: String? let work_eligibility_id: String? let public_seeking_status_id: String? let search_seeking_status_id: String? let days_before_begin_new_job: String? let disc_self_d: String? let disc_self_i: String? let disc_self_s: String? let disc_self_c: String? let location_postal_code: String? let will_relocate: String? let is_default: String? let is_military: String? let website_url: String? let contact_email: String? let contact_mobile: String? let contact_alt_phone: String? let sort_order: String? let disc_adj_nd_id: String? let disc_adj_ni_id: String? let disc_adj_ns_id: String? let disc_adj_nc_id: String? let disc_adj_lw_id: String? let talent_filter_01: String? let talent_filter_02: String? let talent_filter_03: String? let talent_filter_04: String? let talent_filter_05: String? let talent_filter_10: String? let talent_filter_11: String? let talent_filter_12: String? let talent_filter_13: String? let talent_filter_14: String? let talent_filter_15: String? let talent_filter_16: String? let talent_filter_17: String? let talent_filter_18: String? let talent_filter_19: String? let profileSlug: String? let mostRecentWorkHistory: [String:String]? let priorWorkHistories: [WorkHistory]? let mostRecentEducationHistory: [EducationHistory]? let priorEducationHistories: [EducationHistory]? let topQualifications: [TopQualifications]? let seekingLocations: String? let education_level: EducationLevel? let location_country: LocationCountry? let location_timezone: LocationTimeZone? let work_eligibility: WorkEligibility? let public_seeking_status: SeekingStatus? let search_seeking_status: SeekingStatus? let most_recent_work_history: WorkHistory? let most_recent_education: EducationHistory? let disc_adj_nd: DiscAdjData? let disc_adj_ni: DiscAdjData? let disc_adj_ns: DiscAdjData? let disc_adj_nc: DiscAdjData? let disc_adj_lw: DiscAdjData? let js_employer_excludes: [String]? let js_media: [String]? let js_occupations: [JSOccupation]? let js_search_places: [JSSearchPlaces]? let js_work_types: [JSWorkTypes]? let userCoWorkers: [String]? enum CodingKeys: String, CodingKey { case jobSeekerID = "job_seeker_id" case jobseekerName = "job_seeker_name" case linkedInId = "linkedin_id" case firstName = "first_name" case lastName = "last_name" case userID = "user_id" case profilePicture = "profile_pic_file" case personalJobTitle = "personal_job_title" case aboutUser = "about" case userInterest = "interest" case mostRecentWorkHistoryId = "most_recent_work_history_id" case mostRecentEducationId = "most_recent_education_id" case workExperienceYear = "rel_work_exp_year" case mostRecentSalary = "most_recent_salary" case salaryExpectationHigh = "salary_expectation_high" case salaryExpectationLow = "salary_expectation_low" case salaryVisiblePublicProf = "is_salary_on_public_profile" case educationLevelID = "education_level_id" case locationCountryID = "location_country_id" case locationTimezoneID = "location_timezone_id" case workEligibilityID = "work_eligibility_id" case publicSeekingStatusID = "public_seeking_status_id" case searchSeekingStatusID = "search_seeking_status_id" case daysBeforeBeguinJob = "days_before_begin_new_job" case discSelfD = "disc_self_d" case discSelfI = "disc_self_i" case discSelfS = "disc_self_s" case discSelfC = "disc_self_c" case locationPostalCode = "location_postal_code" case willRelocate = "will_relocate" case isDefault = "is_default" case isMilitary = "is_military" case websiteURL = "website_url" case contactEmail = "contact_email" case contactMobile = "contact_mobile" case contactAlternativePhone = "contact_alt_phone" case sortOrder = "sort_order" case discAdjNDID = "disc_adj_nd_id" case discAdjNIID = "disc_adj_ni_id" case discAdjNSID = "disc_adj_ns_id" case discAdjNCID = "disc_adj_nc_id" case discAdjLWID = "disc_adj_lw_id" //probably bool value case talentFilter01 = "talent_filter_01" case talentFilter02 = "talent_filter_02" case talentFilter03 = "talent_filter_03" case talentFilter04 = "talent_filter_04" case talentFilter05 = "talent_filter_05" case talentFilter10 = "talent_filter_10" case talentFilter11 = "talent_filter_11" case talentFilter12 = "talent_filter_12" case talentFilter13 = "talent_filter_13" case talentFilter14 = "talent_filter_14" case talentFilter15 = "talent_filter_15" case talentFilter16 = "talent_filter_16" case talentFilter17 = "talent_filter_17" case talentFilter18 = "talent_filter_18" case talentFilter19 = "talent_filter_19" case profileSlug = "profile_slug" case mostRecentWorkHistoryArray = "mostRecentWorkHistory" case priorWorkHistoriesArray = "priorWorkHistories" case mostRecentEducationHistoryArray = "mostRecentEducationHistory" case priorEducationHistoryArray = "priorEducationHistories" case topQUalificationsArray = "topQualifications" case seekingLocations = "seekingLocations" case educationLevel = "education_level" case locationCountry = "location_country" case locationTimeZone = "location_timezone" case workEligibility = "WorkEligibility" case publicSeekingStatus = "public_seeking_status" case searchSeekingStatus = "search_seeking_status" case discAdjND = "disc_adj_nd" case discAdjNI = "disc_adj_ni" case discAdjNS = "disc_adj_ns" case discAdjNC = "disc_adj_nc" case discAdjLW = "disc_adj_lw" case jobSeekerEmployerExcludes = "js_employer_excludes" case jobSeekerMedia = "js_media" case jobSeekerOccupationsArray = "js_occupations" case jobSeekerSearchPlacesArray = "js_search_places" case jobSeekerWorkTypes = "js_work_types" case userCoWorkers = "user_coworkers" } } struct WorkHistory: Decodable{ let work_history_id : String? let job_seeker_id: String? let position: String? let employer: String? let work_history_name: String? let work_type_id: String? let responsibilities: String? let reason_for_leaving: String? let is_current_position: String? let start_month: String? let start_year: String? let end_month: String? let end_year: String? let sort_order: String? // enum CodingKeys: String, CodingKey { // // case workHistoryID = "work_history_id" // case jobSeekerID = "job_seeker_id" // case position = "position" // case employer = "employer" // case workHistoryName = "work_history_name" // case workTypeId = "work_type_id" // case responsabilities = "responsibilities" // case reasonForLeaving = "reason_for_leaving" // case isCurrentPosition = "is_current_position" // case startMonth = "start_month" // case startYear = "start_year" // case finishMonth = "end_month" // case finishYear = "end_year" // case sortOrder = "sort_order" // } } struct EducationHistory: Decodable { let education_history_id: String? let job_seeker_id: String? let education_level: String? let start_month: String? let start_year: String? let end_month: String? let end_year: String? let educational_institution: String? let program_major: String? let education_history_name: String? let cumulative_gpa: String? let major_gpa: String? let currently_attending: String? let sort_order: String? // enum CodingKeys: String, CodingKey { // // case educationID = "education_history_id" // case jobSeekerID = "job_seeker_id" // case educationLevel = "education_level" // case startMonth = "start_month" // case startYear = "start_year" // case endMonth = "end_month" // case endYear = "end_year" // case educationalInstitution = "educational_institution" // case programMajor = "program_major" // case educationalHistoryName = "education_history_name" // case cumulativeGPA = "cumulative_gpa" // case majorGPA = "major_gpa" // case currentlyAttending = "currently_attending" // case sortEducationOrder = "sort_order" // } } struct TopQualifications: Decodable { let requirement_id: String? let requirement_name: String? let requirement_descr: String? let req_category_id: String? let req_type_id: String? let for_all_occupations: String? // enum CodingKeys: String, CodingKey { // // case requirementID = "requirement_id" // case requirementName = "requirement_name" // case requirementDescription = "requirement_descr" // case requirementCategoryID = "req_category_id" // case requirementTypeID = "req_type_id" // case forAllOccupations = "for_all_occupations" // } } struct EducationLevel: Decodable { let education_level_id: String? let education_level_name: String? let education_level_code: String? let sort_order: String? // enum CodingKeys: String, CodingKey { // // case educationLevelID = "education_level_id" // case edcationLevelName = "education_level_name" // case educationLevelCode = "education_level_code" // case sortOrder = "sort_order" // } } struct LocationCountry: Decodable { let location_country_id: String? let location_country_name: String? let location_country_code: String? let sort_order: String? // enum CodingKeys: String, CodingKey { // // case locationCountryID = "location_country_id" // case locationCountryName = "location_country_name" // case locationCountruyCode = "location_country_code" // case sortOrder = "sort_order" // } } struct LocationTimeZone: Decodable { let location_timezone_id: String? let location_timezone_name: String? let location_timezone_code: String? let sort_order: String? // enum CodingKeys: String, CodingKey { // case locationTimeZoneID = "location_timezone_id" // case locationTimezoneName = "location_timezone_name" // case locationTimezoneCode = "location_timezone_code" // case sortOrder = "sort_order" // } } struct WorkEligibility: Decodable { let work_eligibility_id: String? let work_eligibility_name: String? let work_eligibility_code: String? let sort_order: String? // enum CodingKeys: String, CodingKey { // case workEligibilityID = "work_eligibility_id" // case workEligibilityName = "work_eligibility_name" // case workEligibilityCode = "work_eligibility_code" // case sortOrder = "sort_order" // } } struct SeekingStatus: Decodable { let seeking_status_id: String? let seeking_status_name: String? let seeking_status_code: String? let sort_order: String? // enum CodingKeys: String, CodingKey { // // case seekingStatusID = "seeking_status_id" // case seekingStatusName = "seeking_status_name" // case seekingStatusCode = "seeking_status_code" // case sortOrder = "sort_order" // } } struct DiscAdjData: Decodable { let disc_adj_id: String? let disc_adj_name: String? let disc_adj_code: String? // enum CodingKeys: String, CodingKey { // // case discAdjID = "disc_adj_id" // case discAdjName = "disc_adj_name" // case discAdjCode = "disc_adj_code" // } } struct JSOccupation: Decodable { let occupation_id: String? let occupation_name: String? let occupation_code: String? let job_family_id: String? let soc_coverage: String? let description: String? let education_level_id: String? // enum CodingKeys: String, CodingKey { // case occupationID = "occupation_id" // case occupationName = "occupation_name" // case occupationCode = "occupation_code" // case jobFamilyID = "job_family_id" // case socCoverage = "soc_coverage" // case description = "description" // case educationLevelID = "education_level_id" // } } struct JSSearchPlaces: Decodable { let geo_place_id: String? let country_code: String? let geo_place_code: String? let geo_place_name: String? // enum CodingKeys: String, CodingKey { // // case geoPlaceId = "geo_place_id" // case countryCode = "country_code" // case geoPlaceCode = "geo_place_code" // case geoPlaceName = "geo_place_name" // } } struct JSWorkTypes: Decodable { let work_type_id: String? let work_type_name: String? // enum CodingKeys: String, CodingKey { // // case workTypeID = "work_type_id" // case workTypeName = "work_type_name" // } } After that, I made the request: class JobSeekerJsonRequests: NSObject{ class func jobSeekerRequest(completion: #escaping(_ error: Error?, _ jobSeekerData : JobSeekerDataAPI?) ->Void) { let jsonURLString = URLs.jobSeeker guard let url = URL(string: jsonURLString) else { return } URLSession.shared.dataTask(with: url) { (data, response, error) in guard let data = data else { return } do { let jobSeekerData = try JSONDecoder().decode(JobSeekerDataAPI.self, from: data) print(jobSeekerData) }catch let jsonError { print("Error serializing json: ", jsonError) } }.resume() } And then: func userData(){ JobSeekerJsonRequests.jobSeekerRequest { (error: Error?, jobSeekerData: JobSeekerDataAPI?) in if let jobSeekerData = jobSeekerData { self.myProfileJobTitle.text = jobSeekerData.most_recent_work_history?.position self.menuProfileName.text = jobSeekerData.job_seeker_name self.userNameLabel.text = jobSeekerData.first_name self.userNameJobPositionLabel.text = jobSeekerData.most_recent_work_history?.position self.userLocationLabel.text = jobSeekerData.location_country?.location_country_name self.infoAboutLabel.text = jobSeekerData.about self.userJobTitleLabel.text = jobSeekerData.most_recent_work_history?.position } } I have some problem to understand the API requests becuase I've been working on this and I didn't have any answer from that. I'm learning swift by myself this last 5 month and i'm stuck on this. Sorry If it looks like a stupid question but it's how new guys likes me stuck and need help. Thank you guys!
The way you are using CodingKeys enum is not correct. As stated in Apple docs: The names of the enumeration cases should match the names you've given to the corresponding properties in your type. If the keys used in your serialized data format don't match the property names from your data type, provide alternative keys by specifying String as the raw-value type for the CodingKeys enumeration. The string you use as a raw value for each enumeration case is the key name used during encoding and decoding. In short: case name is exactly same as the property name rawValue of a particular case is the custom key name that you want to use. You are doing exact opposite of what needs to be done. Example: struct JobSeekerDataAPI : Decodable { let job_seeker_id: String? let job_seeker_name: String? //Other properties enum CodingKeys: String, CodingKey { case job_seeker_id = "jobSeekerID" //case name is same as property name case job_seeker_name = "jobseekerName" //Other cases } } For more clarification, refer to: https://developer.apple.com/documentation/foundation/archives_and_serialization/encoding_and_decoding_custom_types You need to do the same for all the structs that you want to be Decodable. This will surely resolve your issue. Edit: Getting nil after decoding the json response data I you are getting nil, check what your API is returning in response. I have included a code snippet of what you API response should look like and what will you obtain as a result: class JobSeekerJsonRequests: NSObject { class func jobSeekerRequest(completion: #escaping(_ error: Error?, _ jobSeekerData : JobSeekerDataAPI?) ->Void) { let jsonResponseString = "{\"jobSeekerID\":\"1234\",\"jobseekerName\":\"abcd\"}" //Something like this must be the format of your JSON response. Check the key names that are used here. guard let data = jsonResponseString.data(using: .utf8) else { return } do { let jobSeekerData = try JSONDecoder().decode(JobSeekerDataAPI.self, from: data) print(jobSeekerData) } catch let jsonError { print("Error serializing json: ", jsonError) } } func userData() { //Your code } } Output you will get after print(jobSeekerData) statement is executed: JobSeekerDataAPI(job_seeker_id: Optional("1234"), job_seeker_name: Optional("abcd")) Just make sure you use the correct key names, since your result completely depends on it. Note: First test your code with less number of properties in struct so that debugging is easy. Adding more code make it difficult to debug the issue. So, start with small and then eventually make it big. Let me know if you still face any issue.
You forgot to add CodingKeys for below in enum CodingKeys: String, CodingKey let most_recent_work_history: WorkHistory? let most_recent_education: EducationHistory?