Access nested array of array of dictionary - ios

I want to display the value of "description" on table view but I am not able to reach to the "description". Every time I loop it. Example
for i in item {
let result = i["description"]
}
It returns Type 'Any' has no subscript members
[[["description": "Meeting", "comments": "", "projectId": 6, "hours": 0.0, "id": 52, "projectName": "A-DA Internal"], ["description": "Others", "comments": "", "projectId": 6, "hours": 0.0, "id": 53, "projectName": "A-DA Internal"], ["description": "3.1 Project Planning", "comments": "", "projectId": 5, "hours": 0.0, "id": 28, "projectName": "STARWorks ESS"], ["description": "4.1 Analysis & Design", "comments": "", "projectId": 5, "hours": 0.0, "id": 32, "projectName": "STARWorks ESS"], ["description": "4.3 Bug fixes", "comments": "", "projectId": 5, "hours": 0.0, "id": 34, "projectName": "STARWorks ESS"]]]

From the response you have posted above its seems the type is [[[String : Any]]].
So to get to the [String: Any] part you will have to dive two level.
//let say
let result: [[[String: Any]]] = THE RESPONSE YOU POSTED..
let item = result.flatmap {$0} //this will convert to [[String: Any]]
//After that your loop will work as expected
for i in item {
debugPrint(i["description"])
}

You need to tell your compiler that the item through which you want to loop through is of type [[String:Any]] only you can get the value for the key description.
You can do that the following way:
for i in item as! [[String:Any]] {
let result = i["description"]
}
Hope this helps. For any queries feel free to leave a comment.

Related

How can I convert JSON to Swift Dictinary inorder to make an HTTP POST

I am having issues to successfully structure my json data into a swift dictionary inorder to send my HTTP body via an API
This is how my Json is structured:
{
"idNo": "string",
"name": "string",
"isRegistered": true,
"customMessage": "string",
"riskStatus": "Low",
"exposureBasedRiskStatus": "Low",
"symptomBasedRiskStatus": "Low",
"riskMessage": "string",
"doYouHaveATemperature": true,
"temperature": 0,
"asessmentQuestion": [
{
"question": "string",
"answer": "string",
"createdBy": "string"
},
{
"question": "string",
"answer": "string",
"createdBy": "string"
},
{
"question": "string",
"answer": "string",
"createdBy": "string"
},
{
"question": "string",
"answer": "string",
"createdBy": "string"
},
{
"question": "string",
"answer": "string",
"createdBy": "string"
}
]
}
the object "asessmentQuestion" is an array of different questions, can't seem to figure out how to convert this structure to a swift dictionary or another recommended format for me to be able to post my data. My API is always saying bad request and I'm pretty sure I am not correctly mapping the json data.
this is a snippet of how I am attempting to map my json data:
var dictionary = [String:Any]()
dictionary["1. How old are you?"] = model.riskExposureBasedAssessment[0].answer
dictionary["2. Have you ever visited a COVID affected country?"] = model.riskExposureBasedAssessment[1].answer
dictionary["3. do you frequently experience flu like symptoms?"] = model.riskExposureBasedAssessment[2].answer
dictionary["4. Where you providing care in a non-health setting for a person with symptomatic COVID-19 infection"] = model.riskExposureBasedAssessment[3].answer
dictionary["5. Did you come in close contact* with a person with symptomatic laboratory-confirmed COVID-19 infection?"] = model.riskExposureBasedAssessment[4].answer
let parameters = [
"idNo": model.id,
"name": model.name,
"isRegistered": model.isRegistered,
"customMessage": model.customResponse,
"riskStatus": model.riskStatus,
"exposureBasedRiskStatus": model.exposureBasedRiskStatus,
"symptomBasedRiskStatus": model.symptomBasedRiskStatus,
"riskMessage": model.riskMessage,
"doYouHaveATemperature": model.doYouHaveATemperature,
"temperature": model.temperature,
"exposureBasedAssessments": dictionary
] as [String:Any]
let postData = try? JSONSerialization.data(withJSONObject: parameters)
It's an array of dictionary, so :
var dictionaries: [[String: Any]] = []
// Populate dictionaries
// ...
let parameters = [
"idNo": model.id,
"name": model.name,
"isRegistered": model.isRegistered,
"customMessage": model.customResponse,
"riskStatus": model.riskStatus,
"exposureBasedRiskStatus": model.exposureBasedRiskStatus,
"symptomBasedRiskStatus": model.symptomBasedRiskStatus,
"riskMessage": model.riskMessage,
"doYouHaveATemperature": model.doYouHaveATemperature,
"temperature": model.temperature,
"exposureBasedAssessments": dictionaries
] as [String:Any]
Then, to populate it:
var dict1: [String: Any] = [:]
dict1["question"] = "1. How old are you?"
dict1["answer"] = model.riskExposureBasedAssessment[0].answer
dictionaries.append(dict1)
var dict2: [String: Any] = [:]
dict2["question"] = "2. Have you ever visited a COVID affected country?"
dict2["answer"] = model.riskExposureBasedAssessment[1].answer
dictionaries.append(dict2)
...
or
var dict1: [String: Any] = ["question": "1. How old are you?",
"answer": model.riskExposureBasedAssessment[0].answer]
dictionaries.append(dict1)
var dict2: [String: Any] = ["question": "2. Have you ever visited a COVID affected country?"",
"answer": model.riskExposureBasedAssessment[1].answer]
dictionaries.append(dict2)
...
But, I guess you have can retrieve the question from model.riskExposureBasedAssessment[n],
Instead of "1. How old are you?", can't you do model.riskExposureBasedAssessment[0].question?
If that's the case, you can use a for loop:
so I'd go with:
for aQuestionModel in model.riskExposureBasedAssessment {
let questionDict = ["question": aQuestionModel.question,
"answer": aQuestionModel.answer]
dictionaries.append(questionDict)
}
Or, once you master basic algorithm, closures, and map():
var dictionaries = model.riskExposureBasedAssessment.map { ["question": $0.question, "answer": $0.answer] }
It's missing the "createdBy", I don't know where to find it and if it's optional, but I think you should be able to add it if needed.
NotaBene:
Code not tested against a compiler. It should work, at maybe one or two typos.

How to get the value of an array of selected keys from swift array of dictionaries and the complexity of it

Lets say I have got the below response. Two things I would like to know from the below operation.
1.) How to improve/optimise the below code using higher order functions in swift.
2.) Also would like to know the current complexity of the code and the complexity of any optimized code you may suggest.
In the below response I would like to check the values of only certain keys as described in keysToBeChecked and for that particular key I need to do an operation. Once the operation is done I want to add a new key(key6) to the response as shown below. The following operation works fine for me and that is what I intend to do. I am looking for the above 2 things mentioned
var response = [["key1": 1, "key2": 0, "name": "John", "key3": 1, "key4": 1, "place": "Newyork", "key5": 0],
["key1": 0, "key2": 1, "name": "Mike", "key3": 1, "key4": 0, "place": "California", "key5": 1],
["key1": 1, "key2": 0, "name": "John", "key3": 0, "key4": 1, "place": "Boston", "key5": 1]]
let keysToBeChecked = ["key1", "key2", "key3", "key4", "key5"]
for var item in response{
var dict = [String: String]()
for(key, value) in item{
if keysToBeChecked.contains(key){
dict[key] = "\(value)"
if dict[key] == "1"{
//perform required operations
output
}
}
}
item["key6"] = output
response.append(item)
}
print(response)//should print the below
My expected output is
response = [["key1": 1, "key2": 0, "name": "John", "key3": 1, "key4": 1, "place": "Newyork", "key5": 0, "key6": "output"],
["key1": 0, "key2": 1, "name": "Mike", "key3": 1, "key4": 0, "place": "California", "key5": 1, "key6": "output"],
["key1": 1, "key2": 0, "name": "John", "key3": 0, "key4": 1, "place": "Boston", "key5": 1, "key6": "output"]]
For higher order function, you can try,
let result = response.map { (dict) -> [String:Any] in
var filteredDict = [String:Any]()
dict.forEach({ (key, value) in
if keysToBeChecked.contains(key) {
filteredDict[key] = value
if (value as? Int) == 1 {
filteredDict["key6"] = "output"
}
}
})
return filteredDict
}

How to i insert a JSON object into an array?

I have a JSON
"passengers": [{
"accompaniedByInfant": true,
"birthDate": {
"day": 6,
"fractionalSecond": 0.000,
"hour": 0,
"minute": 0,
"month": 9,
"orig_day": 6,
"orig_fracSeconds": 0.000,
"orig_hour": 0,
"orig_minute": 0,
"orig_month": 9,
"orig_second": 0,
"orig_timezone": 330,
"orig_year": 1991,
"second": 0,
"timezone": 330,
"year": 1991
},
"hasStrecher": false,
"parentSequence": 0,
"passengerTypeCode": "ADLT",
"gender":"M"
"personName": {
"givenName": "v",
"nameTitle": "MR",
"shareMarketInd": false,
"surname": "j"
},
"requestedSeatCount": 1,
"shareMarketInd": false,
"unaccompaniedMinor": false
}, {
"accompaniedByInfant": false,
"birthDate": {
"day": 10,
"fractionalSecond": 0.000,
"hour": 0,
"minute": 0,
"month": 10,
"orig_day": 10,
"orig_fracSeconds": 0.000,
"orig_hour": 0,
"orig_minute": 0,
"orig_month": 10,
"orig_second": 0,
"orig_timezone": 330,
"orig_year": 2010,
"second": 0,
"timezone": 330,
"year": 2010
},
"hasStrecher": false,
"parentSequence": 0,
"passengerTypeCode": "CHLD",
"personName": {
"givenName": "some",
"shareMarketInd": false,
"surname": "child"
},
"requestedSeatCount": 1,
"shareMarketInd": false,
"unaccompaniedMinor": false
},
and so on depending on the number of passengers.
I have to sent this to the server in
let param : [String: Any] =[ "passengers":passengerparameterarray,"pwd": password,"requestPurpose": "MODIFY_PERMANENTLY_AND_CALC","unm": username ]
Here passengerparameterarray is an array of type string.(here is the issue). I stored details of each passenger in an array
paramarray and whenever user finishes adding details, paramarray is added to the passengerparameterarray on position depending on the indexPath. (1 passenger = added on 0th index, 2 = on 0th and 1st index and so on).
But when I send it to server it goes like
"passengers" : [ [ ..... ] ]
This gives me error as I have an array inside of the array. How do I fix this? I try changing to string but that gives me error as String isn't JSON object because of the " coming before { .
I converted each array to JSON Object. But how do i JSON Object the main array? As the Main array is [String]() . If i try changing to [String:Any]() , things like
array.insert()
Wont work.
How do I fix this? I want to add the JSON object into an array and then sent it to the server.
try this
var param : [String:Any] = ["requestedSeatCount" : 1, "gender" : "M", "parentSequence" : 0, "passengerTypeCode" : "ADLT", "shareMarketInd" : false]
param.updateValue(["nameTitle" : "MR", "givenName" : "aaaa", "surname" : "aaa"], forKey: "personName")
param.updateValue(["year" : "2019", "day" : "29", "month" : "5"], forKey: "birthDate")
This was a stupid question. This all happened because originally my array was
var passengerparameterarray = [Array<Any>]()
instead of
var passengerparameterarray = Array<[String: Any]>()
Which as expected stopped me from inserting JSON object which is in the form of "String:Any"

How to find key in a NSDictionary object array ios

I have a NSMutableArraylike this.
[
{
"Employee": {
"EmployeeCode": 17125,
"DisplayName": "MI0000026 - ABC",
"DisplayName2": "ABC2",
"Initials": "W. S. S.",
"Surname": "CCC",
"FirstName": "ABC",
"MiddleName": "CDE",
"LastName": "",
"FullName": "ABC EMPLOYEE",
},
"LeaveDetail": {
"LeaveDetailId": 21,
"LeaveEntryCode": 16,
"RequestId": 20,
"EmployeeCode": 17125,
"LeaveYear": 2016,
"LeaveTypeCode": 1,
"BaseType": "ess",
"LeaveDate": "2016-09-05T00:00:00",
}
}
]
there are several objects in this array which has these kind of dictionaries. I want to find all the objects in this array which has "LeaveDate": "2016-09-05T00:00:00" this LeaveDate key is inside the LeaveDetail dictionary. How can I find all the objects which has LeaveDate as "2016-09-05T00:00:00"
EDIT
NSPredicate *predicate=[NSPredicate predicateWithFormat:#"LeaveDate CONTAINS[cd] %#",dm.strClickedDate];
But, I don't get any result.
Please help me.
Thanks
NSDictonary *dict = [yourMutableArray[0]];//get dict in array with index = 0
NSLog(#"%#",dict);
//*Log dict will show:
{
"Employee": {
"EmployeeCode": 17125,
"DisplayName": "MI0000026 - ABC",
"DisplayName2": "ABC2",
"Initials": "W. S. S.",
"Surname": "CCC",
"FirstName": "ABC",
"MiddleName": "CDE",
"LastName": "",
"FullName": "ABC EMPLOYEE",
},
"LeaveDetail": {
"LeaveDetailId": 21,
"LeaveEntryCode": 16,
"RequestId": 20,
"EmployeeCode": 17125,
"LeaveYear": 2016,
"LeaveTypeCode": 1,
"BaseType": "ess",
"LeaveDate": "2016-09-05T00:00:00",
}
}
*//
NSDictionay *leaveDetailDict = [dict objectForKey:#"LeaveDetail"];//get dict have key LeaveDetail
NSLog(#"%#",leaveDetailDict[#"LeaveDate"];

How to sort multidimensional array in swift?

I need your help. I did an array, and when I launch my application on different devices or simulator, this array sorted into different types, but I need the same order on each device. How to do that?
var settings = [String: [ [String: String] ]]()
settings = [ "cards":[ ], "groups":[ ] ]
...
for card in db.prepare(table.order(orderN.asc)) {
settings["cards"]?.append(["id":String(card[id]), "group_id":String(card[group_id]), "service":card[service], "bgcolor":card[bgcolor], "logoimg":card[logoimg]!, "balance_desc":card[balance_desc], "balance":"0.0", "balance_id":String(card[balance_id]), "uniqueID":card[uniqueID], "balance_currency":String(card[balance_currency]), "orderN":String(card[orderN])])
}
...
for group in db.prepare(table.order(orderN.asc)) {
settings["groups"]?.append(["name":group[name]!,"id":String(group[id]),"orderN":String(group[orderN])])
}
...
For example,
On the first device
print(settings) // ["cards": [["orderN": "0", "bgcolor": "0.0, 0.0, 0.0, 1.0", "balance": "0.0", "logoimg": "example.com/images/img.png", "uniqueID": "00a2413f74f4a3f186e439a67057de67", "group_id": "2", "id": "1", "service": "servicename", "balance_desc": "Description", "balance_id": "1", "balance_currency": "1"]], "groups": [["orderN": "0", "name": "GroupName", "id": "2"]]]
On the second device
print(settings) // ["cards": [["orderN": "0", "uniqueID": "00a2413f74f4a3f186e439a67057de67", "service": "servicename", "id": "1", "bgcolor": "0.0, 0.0, 0.0, 1.0", "balance_currency": "1", "balance": "0.0", "group_id": "2", "logoimg": "example.com/images/img.png", "balance_id": "1", "balance_desc": "Description"]], "groups": [["id": "2", "orderN": "0", "name": "GroupName"]]]
Thank you for you attention.
That's because settings is not an Array, it's Dictionary. Order of key-value pairs in dictionary is not defined.
If you need some particular order, you should reimplement settings, probably make them separate struct or class, because you'll have a hard time working with nested dictionaries.

Resources