How to create Mixed Pattern Dictionaries in Swift - ios

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"
]

Related

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"]]

Creating new Dict from values of another

I have JSON like this:
{
"SKzSjdBuOpO49wkPVaxtmLQoR0O2": {
location: "-LB1fn5GQKTaIc-fGNPS"
},
"s0ntSZP7mBQw1a8ua0E5PqazlqJ2": {
location: "-LB23izD7bp2NhO0UuIo"
},
"FEScjelpNSR7vuVz1ha6Z6uSfF43": {
location: "-LB1JLABuJO1NyJ-v2t_"
},
"mW7dGja6cRRB0d9uSIhg4f35PzC3": {
location: "-LB5xqUvIjEgtW_FH_nG"
},
"GCnt0VKcqjT8bl2chw43nsntaZK2": {
location: "-LB1n8ga9C0vCcZXD2Us"
}
}
in my Values[String: Any] dictionary. And i want to Create another dictionary from its values to access location value.
Can you help me to do this?
If the primary goal is just to access the values and the type is fixed to [String: Any], do it like this:
if let info = dictionary["SKzSjdBuOpO49wkPVaxtmLQoR0O2"] as? [String : String] {
let location = info["location"]
}
Try not to use Dictionary in swift, rather for your case you can use [String : [String: String]] type and then loop through you data to get the required values. Try this
let dict = ["SKzSjdBuOpO49wkPVaxtmLQoR0O2": [
"location" : "-LB1fn5GQKTaIc-fGNPS",
], "s0ntSZP7mBQw1a8ua0E5PqazlqJ2": [
"location" : "-LB23izD7bp2NhO0UuIo",
], "FEScjelpNSR7vuVz1ha6Z6uSfF43": [
"location" : "-LB1JLABuJO1NyJ-v2t_",
], "mW7dGja6cRRB0d9uSIhg4f35PzC3": [
"location" : "-LB5xqUvIjEgtW_FH_nG",
], "GCnt0VKcqjT8bl2chw43nsntaZK2": [
"location" : "-LB1n8ga9C0vCcZXD2Us",
]]
var newDict = [String: String]()
for (key, val) in dict {
newDict[key] = val["location"]
}
print(newDict)
Output:
["SKzSjdBuOpO49wkPVaxtmLQoR0O2": "-LB1fn5GQKTaIc-fGNPS",
"s0ntSZP7mBQw1a8ua0E5PqazlqJ2": "-LB23izD7bp2NhO0UuIo",
"FEScjelpNSR7vuVz1ha6Z6uSfF43": "-LB1JLABuJO1NyJ-v2t_",
"mW7dGja6cRRB0d9uSIhg4f35PzC3": "-LB5xqUvIjEgtW_FH_nG",
"GCnt0VKcqjT8bl2chw43nsntaZK2": "-LB1n8ga9C0vCcZXD2Us"]
Edit
For your case as you have dictionary, you can try this:
let dict = ["SKzSjdBuOpO49wkPVaxtmLQoR0O2": [
"location" : "-LB1fn5GQKTaIc-fGNPS",
], "s0ntSZP7mBQw1a8ua0E5PqazlqJ2": [
"location" : "-LB23izD7bp2NhO0UuIo",
], "FEScjelpNSR7vuVz1ha6Z6uSfF43": [
"location" : "-LB1JLABuJO1NyJ-v2t_",
], "mW7dGja6cRRB0d9uSIhg4f35PzC3": [
"location" : "-LB5xqUvIjEgtW_FH_nG",
], "GCnt0VKcqjT8bl2chw43nsntaZK2": [
"location" : "-LB1n8ga9C0vCcZXD2Us",
]] as Dictionary<String, Any>
var newDict = [String: String]()
for (key, val) in dict {
if let value = val as? [String: String] {
newDict[key] = value["location"]
}
}
print(newDict)

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.

iOS swift json PUT request string array in parameters

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

SwiftyJSON and adding to existing [String: AnyObject] dictionary

This is the JSON I am looking to parse with the SwiftyJSON library:
{
array: [
{ a: "something", b: "something" },
{ a: "something", b: "something" },
{ a: "something", b: "something" }
]
}
The catch is that the array count will have variable amount of objects. Normally I would just create a Dictionary with [String: AnyObject], but can't do a for loop inside it.
var parameters: [String: AnyObject] = [
"array": [
]
]
Is there any way I can append/add [String: AnyObject] elements to an existing Dictionary ("array" dictionary)?
I would then convert it to a JSON with the SwiftyJSON lib.
I would suggest constructing the inner array first. It is possible to reach into your nested data structure and modify things, but tricky because you have to be very careful about types.
var innerArray: [AnyObject] = []
for i in 0...2 {
innerArray.append(["a":"something","b":"something"])
}
var parameters: [String: AnyObject] = ["array": innerArray]

Resources