SwiftyJSON and adding to existing [String: AnyObject] dictionary - ios

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]

Related

Swift: Remove keys and values added during array flatMap conversion

Trying to make array of dictionaries with object, which adds keys and values during array flatMap
var parameters: [String: Any] {
var postParameters: [String: Any] = [:]
postParameters["topics"] = categories.flatMap({ toPostParameters($0) })
print(postParameters)
return postParameters
}
private func toPostParameters(_ topics: Topics) -> [String: Any] {
var params: [String: Any] = [:]
params["id"] = topics.id
params["isFound"] = topics.isFound
return params
}
when I print the postParameters value, all I get is like the following. How to remove the key and value strings appending over it.
["topicCategories": [(key: "isFound", value: true), (key: "id", value: "62ef2b63e49a"),
(key: "id", value: "632serer269"), (key: "isFound", value: true)]]
Expected
["topicCategories": [["isFound": true, "id": "62ef2b63e49a"],
["id": "632serer269","isFound": true]]]
You should use map, because flatMap makes everything "flat" and you get a flat array of tuples instead of array of dictionaries.
Example:
class Topics {
var id = 1
var isFound = true
}
var categories = [Topics(), Topics(), Topics()]
var parameters: [String: Any] {
var postParameters: [String: Any] = [:]
postParameters["topics"] = categories.map({ toPostParameters($0) })
return postParameters
}
private func toPostParameters(_ topics: Topics) -> [String: Any] {
var params: [String: Any] = [:]
params["id"] = topics.id
params["isFound"] = topics.isFound
return params
}
print(parameters)
Output:
["topics": [["id": 1, "isFound": true], ["id": 1, "isFound": true], ["isFound": true, "id": 1]]]
P.S:
Good article to understand the difference between map, compactMap and flatMap.

How to check if dictionary value is string or an array

I have data from server like
[
{
"id": 1,
"name": "16",
"children": "",
"products": [
{...},
{...}
]
},
{
"id": 2,
"name": "17",
"children": "",
"products": [
{...},
{...}
]
}
]
so I save it like [[String: Any]], and Any is because there can be Int, String or Dict at the values.
The point is that "children" key can be NSConstantstring and can be casted to String, and also it can be NSArray and can be casted to [[String: Any]] too. So I need to find a way to detect type of that value. But all I tried caused error.
How can i fix this?
UPD
not much code)
inside alamofire response:
let data = responseJSON.result.value! as! [String: Any]
let subCategory = data["children"] as! [[String: Any]]
//check
for item in subCategory {
print(type(of: item["children"]!))//__NSArrayI or __NSCFConstantString
}
if I try something like print(type(of: item["children"] as! String)) it prints String if there is __NSCFConstantString, but if not - it crashes with error Could not cast value of type '__NSArrayI' (0x10934fe48) to 'NSString' (0x1083e8568)
UPD 2
there is no problem with data, all parsed and save correctly and printing out correctly too
You can just cast value from dictionary to needed type:
if let string = dictionary["children"] as? String {
// Do something with string
} else if array = dictionary["children"] as? [Any] {
// Do something with array
}

Retrieve Firebase dictionary data in Swift

I have a Firebase Database structured like this:
results: {
A: [
{data}
],
B: [
{data}
],
C: [
{data}
],
....
}
It is a dictionary of values sorted alphabetically.
My question is, what would be the best way to retrieve this data in swift?
Generally, the most common practice for retrieving Firebase data is to cast the snapshot's value to a Swift Dictionary like this:
let myRef = FIRDatabase.database().reference().child("results")
myRef.observeSingleEvent(of: .value, with: { (snapshot) in
if !snapshot.exists() {
// handle data not found
return
}
// data found
let myData = snapshot.value as! [String: Any] // the key is almost always a String
// extracting data from the dictionary
let A = myData["A"] as! [String: Any]
let dataInA = A["anyChildOfA"] as! Double
// ...
})
It doesn't really matter if the data is sorted or not on Firebase, retrieval would be of the same complexity
Update
You can simply loop over all the alphabets to extract the data:
var extractedData = [[String: Any]]() // array of Swift Dictionary
for c in "ABCDEFGHIJKLMNOPQRSTUVWXYZ".characters {
let temp = myData[String(c)] as! [String: Any]
extractedData.append(temp);
}
extractedData[0] would be the data in A, extractedData[25] would be the data in Z. That, of course, is assuming you have a child for each letter.
Create a struct to present "data":
struct Data {
...
}
Create a wrapper:
struct DataWrapper {
let data: [Data]
}
Then, create a new model:
struct ModelName {
results: [DataWrapper]
}

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

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

Resources