iOS swift json PUT request string array in parameters - ios

I'm working with Alamofire and SwiftyJSON.
I'm trying to make a request with the following structure
{
"email":"ppp#ppp.com",
"password":"pppppp",
"categories": [
{"id":"2"},
{"id":"1"},
{"id":"6"},
{"id":"5"}
]
}
I'm using :
let parameters = [
"email" : userEmail,
"categories" : userPassword,
"categorias" : selectedCategoriesArray]
//where selectedCategoriesArray is a [[String]]()
I fill my selectedCategoriesArray in a loop with this line modifying the array:
selectedCategoriesArray.append(["id", "2"]) //where 2 can be any other number
Alamofire.request( .PUT, url, parameters)
It seems it's working fine but it isn't, I don't know if my String array is taking the right format to be sent to the WS or do I need to encode it in a special way?
Has anyone worked with something like this, A little help would be appreciate.
Thanks!

I think your array should have a type of [[String: String]] in this case.
let userEmail = "myemail#email.com"
let userPassword = "123456"
var selectedCategoriesArray: [[String: String]] = []
for i in 0...5 {
selectedCategoriesArray.append(["id": String(i)])
}
let parameters = [
"email" : userEmail,
"password" : userPassword,
"categories" : selectedCategoriesArray
]

Check with below
let savedData = ["id": 1, "id": 2]
let jsonObject: [String: AnyObject] = [
"email": “xyz#yopmail.com”,
"password": 123456,
"categories": savedData
]
let valid = NSJSONSerialization.isValidJSONObject(jsonObject) // true

Related

(iOS) In firebase Analytics "kFIRParameterItems" parameter not accept array and its returns an error "InvalidArrayParamEventName (21)"

//Array not accept in Firebase Analytics on "kFIRParameterItems" parameters
var arrCompleteItems = [Any]() // create array to set on "kFIRParameterItems"
for obj in headerItems{
if let items = ServicesContainerViewModel.cartData[obj.id] as? [String: Any] {
if let data = items[InputKeys.items] as? [Item_list] {
for obj in data{
let itemDetails: [String: Any] = [
AnalyticsParameterItemID: obj.id ?? "",
AnalyticsParameterItemName: obj.name ?? "",
AnalyticsParameterItemCategory: obj.parentCategoryName ?? "",
AnalyticsParameterQuantity : obj.itemQuantity ?? ""
]
arrCompleteItems.append(itemDetails)
}
}
}
}
let itemDetails: [String: Any] = [
AnalyticsParameterCurrency: "INR",
AnalyticsParameterValue: "",
AnalyticsParameterItems: arrCompleteItems ,
"user_name": Person.sharedInstance.firstName,
"email": Person.sharedInstance.email,
"mobile_number": Person.sharedInstance.mobileNumber
]
Analytics.logEvent(FirebaseAnalyticsHelper.isTesting+AnalyticsEventViewCart, parameters: parameters)
Resolved this issue with default event name,
Analytics.logEvent(AnalyticsEventViewCart, parameters: parameters)
I noticed that you are unable to see ITEMS parameter in the Firebase console. Upon checking, there is an internal bug filed on Firebase end. It’s expected that it will not show yet in the Firebase Console (DebugView, dashboard, etc.). However, this parameter can be seen in BigQuery, but it’s only supported for the Retail/Ecommerce events.

Create Dictionary from Array in Swift 5

I need to create a dictionary from array with custom type for first index of the array.
Sample array : ["ABC","ZYZ","123"]
Required result : [{"name" : "ABC", "type:"A"},{"name" : "ZYZ", "type:"B"},{"name" : "123", "type:"B"}]
Note type A for first index.
My code
for url in urlArray {
urlDict["name"] = url
}
You can do a map, and then individually change the type of the first dictionary:
var dicts = urlArray.map { ["name": $0, "type": "B"] }
dicts[0]["type"] = "A"
Seeing how all your dictionary keys are all the same, and that you are sending this to a server, a Codable struct might be a better choice.
struct NameThisProperly : Codable {
var name: String
var type: String
}
var result = urlArray.map { NameThisProperly(name: $0, type: "B") }
result[0].type = "A"
do {
let data = try JSONDecoder().encode(result)
// you can now send this data to server
} catch let error {
...
}
I suppose you can use a high order function such as map or reduce
Here is an example using reduce
var array = ["ABC","ZYZ","123"]
var result = array.reduce([[String: String]](), { (previous, current) -> [[String: String]] in
let type = previous.count == 0 ? "A" : "B"
let dictForCurrent = [
"name": current,
"type": type
]
return previous + [dictForCurrent]
})
print(result)
The result:
[["type": "A", "name": "ABC"], ["type": "B", "name": "ZYZ"], ["name":
"123", "type": "B"]]
Use reduce to convert array to dictionary:
let resultDict: [String: String]
= array.reduce(into: [:]) { dict, url in
dict["name"] = url
}
The result will look like:
[
"name": URL1,
"name": URL2
]
Use map(_:) to convert each element of the array to dictionary like so,
let arr = ["ABC","ZYZ","123"]
let result = arr.map { (element) -> [String:String] in
var dict = [String:String]()
dict["name"] = element
if let char = element.first {
dict["type"] = String(char)
}
return dict
}
print(result)
since you are concern about the index, my approach will be using enumerated() which gives out the index
let array = ["ABC","ZYZ","123"]
var results: [[String: String]] = []
for (i, content) in array.enumerated() {
let type: String = i == 0 ? "A" : "B"
results.append(["name": content, "type": type])
}
print(result)
// [["type": "A", "name": "ABC"], ["name": "ZYZ", "type": "B"], ["type": "B", "name": "123"]]

Add json objects to array

On click of a submit button the data in my textfields and some other data are being converted to a json object like so…
let categoryName = self.categoryTextField.text
let categoryId = self.categoryID
let category_json: [String: [String:Any]] = [
"categoryDetails": [
"category_name": categoryName,
"category_id": categoryId
]
]
if let data = try? JSONSerialization.data(withJSONObject: category_json, options: .prettyPrinted),
let str = String(data: data, encoding: .utf8) {
print(str) // `str` gives the json object
self.categoryStrToPass = str
}
Now self.categoryStrToPass is assigned to another json object and then finally added to a string array like so…
let productID = self.prodID
let sellingPrice = self.mrpTextField.text
let categoryJSON = self.categoryStrToPass
let jsonObject: [String: [String:Any]] = [
"prodDetails": [
"product_id": productID,
"selling_price": sellingPrice,
“category_json”: categoryJSON
]
]
if let data = try? JSONSerialization.data(withJSONObject: jsonObject, options: .prettyPrinted),
let str = String(data: data, encoding: .utf8) {
print(str)
self.jsonStrToPass = str
self.jsonStringArray.append(self.jsonStrToPass)
}
Now I’m storing jsonStringArray to coredata like so…
_product?.setValue(self.jsonStringArray, forKey:
"productJsonArray") // productJsonArray is an attribute of type Transformable and Custom class type Array<String>
And it is being fetched like so...
if let jsonObjArr = result.value(forKey: "productJsonArray") as?
Array<NSString> {
print(jsonObjArr)
}
Now on 2 different instances I have submitted the data which means on printing jsonObjArr while fetching,it should have 2 different json objects in one array like so..
[{
"prodDetails" : {
"product_id" : "0",
"category_json" : "{\n \"categoryDetails\" : {\n \"category_id\" : \"0\",\n \"category_name\" : \"prodCAT\"\n }\n}",
"selling_price" : "500",
}
}
{
"prodDetails" : {
"product_id" : "1",
"category_json" : "{\n \"categoryDetails\" : {\n \"category_id\" : \"0\",\n \"category_name\" : \"CATNEW\"\n }\n}",
"selling_price" : "1000",
}
}]
But instead, printing jsonObjArr is giving this…in 2 different arrays like so...
[{
"prodDetails" : {
"product_id" : "0",
"category_json" : "{\n \"categoryDetails\" : {\n \"category_id\" : \"0\",\n \"category_name\" : \"prodCAT\"\n }\n}",
"selling_price" : "500",
}
}]
[{
"prodDetails" : {
"product_id" : "1",
"category_json" : "{\n \"categoryDetails\" : {\n \"category_id\" : \"0\",\n \"category_name\" : \"CATNEW\"\n }\n}",
"selling_price" : "1000",
}
}]
How can I get multiple json objects in one single array...?
you can add objects of type [String: Any] to array like so
let firstCategoryName = "first"
let firstCategoryId = 1
let firstCategory = [
"category_name": firstCategoryName,
"category_id": firstCategoryId
] as [String : Any]
let secondCategoryName = "second"
let secondCategoryId = 2
var category_json = [[String:Any]]()
category_json.append(firstCategory)
let secondCategory = [
"category_name": secondCategoryName,
"category_id": secondCategoryId
] as [String : Any]
category_json.append(secondCategory)
print(category_json)
then serialize the array
Swift 4.0:
let firstObj = ["prodDetails": [
"product_id": 5,
"selling_price": 6,
]]
let secondObj = ["prodDetails1": [
"product_id1": 5,
"selling_price1": 6,
]]
let jsonObject = jsonStringArray.addingObjects(from: [firstObj,secondObj])
if let data = try? JSONSerialization.data(withJSONObject: jsonObject, options: .prettyPrinted),
let str = String(data: data, encoding: .utf8) {
print(str) //prints array of dictionaries
}
category_json and jsonObject are of the same kind.
What you need to understand:
(NS)String <== String(data:encoding) or data(encoding:) ==> (NS)Data
Applied to specific String/Data: JSON:
JSON Stringified <== String(data:encoding) or data(encoding:) ==> JSON Data
Swift Array/ Swift (and the rest JSON compliant) <== (NS)JSONSerialization.jsonObject(withData:, options:) or (NS)JSONSerialization.data(withJSONObject:, options:) ==> JSON Data
You can't append like that the two JSON Stringified, you need to have an array at least at top level.
So, let's connect the dots, in pseudo code (not sure at all that the method name are error free)
let currentData = self.jsonStrToPass.data(encoding: .utf8)
let current = JSONSerialization.jsonObject(with:currentData, options:[]) as [String:[String:Any]]
let finalArray : [[String:[String:Any]]]()
finalArray.append(current)
finalArray.append(jsonObject)
let finalData = JSONSerialization.data(withJSONObject:finalArray, options:[])
let finalString = String(data:finalData, encoding:.utf8)
That's for the logic. I didn't do the if let, try/catch, etc.
I'd think it might be better to pass Any (for Swift Array/Dictionary instead of String) between your data to pass. It might be simpler to edit them (append, etc.) instead of String.

Create specific Json in Swift 4

I have to deliver some specific JSON to a webserver, but I'm very confused about how to use the correct arrays and dictionaries, so I can't get to my final result. I'm starting from this:
["entries": [
"member" : [
"id" : key,
"name" : value
],
"timestamp" : "\(dateString)"
]
]
in the JSON file I have to send to the server I can only have 1 "entries" and several "member" with specific "id" and "name" and timestamp. I'm aware that I have to use dictionaries but can't get to this result. This is what I tried so fare:
var leden = [Int: String]()
var jsonDict = [String: Any]()
var dateString = Date()
for (key, value) in leden{
jsonDict["\(key)"] = ["member" : [
"id" : key,
"naam" : value
],
"timestamp" : "\(dateString)"
]
}
jsonFinaal = ["entries": jsonDict]
this is as close as I could get, but good enough because the key in jsonDict should not be there, I added the "entries" in a second dictionary to make this a unique entry.
Anyone who can do beter to help me to the solution?
The value for members is an array of dictionaries, not a dictionary
This creates the structure sorted by the id keys
let leden = [1 : "Foo", 2: "Bar"]
let sortedKeys = leden.keys.sorted()
let dateString = Date()
var members = [[String:Any]]()
for key in sortedKeys {
let naam = leden[key]!
members.append(["member" : ["id" : key, "naam" : naam], "timestamp" : "\(dateString)"])
}
let entries = ["entries": members]
print(entries)
And the JSON string with
do {
let jsonData = try JSONSerialization.data(withJSONObject: entries)
let json = String(data: jsonData, encoding: .utf8)
print(json)
} catch { print(error) }

How to create Mixed Pattern Dictionaries in Swift

I am trying to create a mixed pattern dictionary in Swift which contains either String:String or String:Dictionary as below. Can anyone help?
var tempDict = ["Electronics":"TV"],["Home":["Kitchen":"Utensils"],["BedRoom":"Bed "],["DiningRoom":"Dining"]]
I may be missing what you really want to do, but you can declare a dictionary like this:
var tempDict = ["Electronics":"TV","Home":["Kitchen":"Utensils"],"BedRoom":"Bed ","DiningRoom":"Dining"]
Swift (as of 2.2.1) infers the type of tempDict as [String: NSObject], so you can use the values with casting:
if let electronics = tempDict["Electronics"] as? String {
print(electronics)
}
if let home = tempDict["Home"] as? [String: String] {
print(home)
}
Use AnyObject:
var tempDict: [String: AnyObject] = ["Electronics":"TV"]
tempDict = ["Home":["Kitchen":"Utensils"]
["BedRoom":"Bed "],
["DiningRoom":"Dining"]]
var tempDict = [
"ElectronicsString" : "TV",
"HomeDic" : [
[
"Kitchen" : "Utensils",
"BedRoom":"Bed ",
"DiningRoom":"Dining",
]
],
"BetArray" : [
"cat",
"dog"
]
]
By the way, if a dictionary is a big compounded dictionary, the complier of Swift will have error. So you can solve it like this:
var tempDict: [String: AnyObject] = [
"ElectronicsString" : "TV"
]
tempDict["HomeDic"] = [
[
"Kitchen" : "Utensils",
"BedRoom":"Bed ",
"DiningRoom":"Dining",
]
]
tempDict["BetArray"] = [
"cat",
"dog"
]

Resources