I have 3 arrays when I insert data inside table than that data also add in the array (key, value pair).
var person = ["ABC","XYZ","PQR"]
var email = ["abc#yahoo.com","xyz#yahoo.com","pqr#yahoo.com"]
var mobile = ["1234567890","1234567890","1234567890"]
My problem is how to create JSON object and data store key value pair.
I want this
{
"blogs": [
{
"person": "ABC",
"email": "abc#yahoo.com",
"contact": "1234567890"
},
{
"person": "XYZ",
"email": "xyz#yahoo.com",
"contact": "1234567890"
},
{
"person": "PQR",
"email": "pqr#yahoo.com",
"contact": "1234567890"
}
]
}
so that data passes to url()
In the action button that adds data in array and table
#IBAction func meeting_info(_ sender: Any) {
var PersonName = person_name.text
var Email = email_id.text
var MobileNo = mobile_no.text
if (person_name.text?.isEmpty)! || (email_id.text?.isEmpty)! || (mobile_no.text?.isEmpty)! {
displayMyAlertMessage(userMessage: "please check field empty or not");
}
else{
person.append(person_name.text!)
email.append(email_id.text!)
mobile.append(mobile_no.text!)
meetingTableView.reloadData()
}
}
I want to generate JSON array from person, email and contact in key value pairs
to answer your question.
var person = ["ABC","XYZ","PQR"]
var email = ["abc#yahoo.com","xyz#yahoo.com","pqr#yahoo.com"]
var mobile = ["1234567890","1234567890","1234567890"]
var paramCollection = [Any]()
var index = 0
for personData in person {
var dataCollection = [String:Any]()
dataCollection["person"] = personData
dataCollection["email"] = email[index]
dataCollection["contact"] = mobile[index]
paramCollection.append(dataCollection)
index += 1
}
let finalParameter = ["blogs":paramCollection]
}
//This will do the trick but to make it more robust you should rethink your design
// maybe use struct to store a persons data
struct Blog {
var person: String
var email: String
var mobile: String
init(name:String, email:String, phone:String) {
self.person = name
self.email = email
self.mobile = phone
}
}
//and instead of having three arrays holding three different property, you can have one array of
var blogArray = [Blog]()
//You understand where I'm going with this
This is not a great design by choice to have multiple arrays relating to the data of same Entity.
Ideally create an Entity Model called Blog with fields like personName, email, mobileNo like below -
struct Blog {
var personName: String?
var email: String?
var mobileNo: String?
}
And then in your code have an array of this to save the data then you can directly convert it into Json using the link
Convert Custom Structs to Json
Try this:
let jsonObject: [String: Any]?
let array: [[String: Any]] = [[:]]
for i in 0..person.count {
let dict = ["person": person[i],
"email": email[i],
"contact": mobile[i]]
array.append(dict)
}
jsonObject = ["blogs": array]
let validateJson = JSONSerialization.isValidJSONObject(jsonObject)
if validateJson {
//Go Ahead
}
let dictionary = ["key1": "value1", "key2": "value2"]
let jsonData = try? JSONSerialization.data(withJSONObject: dictionary, options: .prettyPrinted)
// Verifying it worked:
let parsedObject = try! JSONSerialization.jsonObject(with: jsonData!, options: .allowFragments)
Related
I'm using Json Object to display in tableview.I parsed Json successfully print data also. and I'm using foreach statement to get the data into variable But the problem is I'm getting in variable the last item in json object. I want to display user to name variable to present name on it
here is my Json data
{
"Categories": [
"school, class"
],
"Tags": [
{
"Value": "ashok",
"Key": "Name"
}, {
"Value": "III",
"Key": "class"
}, {
"Value": "A",
"Key": "section"
}
]
}
here is my model array
struct classInfo: Decodable {
let Categories: String
let Tags: String
let Value: String
let Key: String
var Name: String
let class: String
}
here is my code
var ClassList = [classInfo]()
var name: String = ""
var class: String = ""
In JSONSerialization FUNCTION
do{
let json = try JSONSerialization.jsonObject(with: data!, options: []) as! [String: AnyObject]
print(json as AnyObject)
let cat = json["Categories"] as? [String: Any]
print(cat!)
if let array = json["Tags"] as? [[String: Any]] {
for obj in array {
if let dict = obj as? NSDictionary {
// Now reference the data you need using:
let Value = dict.value(forKey: "Value")
let Key = dict.value(forKey: "Key")
print(Value!)
print(Key!)
self.name = tag["Value"] as! String
print(self.name)
self.class = tag["Value"] as! String
print(self.class)
}
}
}
IN CELL FOR ROW FUNCTION
cell.Name.text = "Name:\(name)"
cell.class.text = "class: \(class)"
use this
class ModelClass{ var name:String ; var classs:String }
class ModelDataClass { static var modelData = [ModelClass]() }
in your viewController. - add values in models and
in you cellForRowAt -- >
cell.nameTextLabel.text = ModelDataClass.modelData[indexPath.row].name
cell.classsTextLabel.text = ModelDataClass.modelData[indexPath.row].classs
heyy , try this then ,
class ModelClass {var name:String}
now create a custom tableView cell
class CustomTableViewCell:UITableViewCell {
var dataModel : ModelClass?{
didSet{
guard let model = dataModel else {return}
print(model.name)
// set label text here : ex := myLabel.text = model.name
}
}
// declare all IBLayouts or create them programmatically... its your choice
}
in Your tableView cell (cellForRowAt ---> )
use this snippet
var dataModel = [ModelClass]()
dataModel = [ModelClass(name:"Rishabh"),ModelClass(name:"Adi"),ModelClass(name:"FFFf")]
now pass this dataModel to cellDAtaModel by using
let cell = tableView.deq() as! CustomTableViewCell //deq() - > to lazy to type whole lol ;P type by yourself
cell.dataModel = dataModel[indexPath.row]
I am still getting familiar with Swift, and I am having troubles with adding objects to an array at this moment.
Also the array shouldn't have duplicates.
What I have so far -
A function that is called when user does a button click on a prototype cell.
I am trying to achieve -
Select button (and indicate with a checkmark that he selected/deselected the item)
For each selected item, I have two values - bool status isActive and the selected item's subscriptionID
When user selects the item, I need to add this selection as an object and further append this to an array.
For that, I have subscriptionUpdateData: NSDictionary and my new empty array subscriptionsArray: [NSDictionary] = []
Full Function
func subscriptionCell(cell: SubscriptionCell, didToggleSubscription subscription: Subscriptions) {
var subscriptionsArray: [NSDictionary] = []
var subscriptionUpdateData: NSDictionary = ["subscriptionID": 0, "isActive": false]
if let matchingSubscription = subscriptionInformation?.filter({ $0.subscriptionID == subscription.subscriptionID }).first {
matchingSubscription.isActive = !(matchingSubscription.isActive!)
let subscriptionStatus = matchingSubscription.isActive
let subscriptionStatusForId = matchingSubscription.subscriptionID
subscriptionUpdateData = ["subscriptionID": subscriptionStatusForId!, "isActive": subscriptionStatus!]
tableView.reloadData()
}
subscriptionsArray.append(subscriptionUpdateData)
print("\(subscriptionsArray)")
}
What is going on with above -
I am able to select an item, form it as a dictionary, and add it to my array. :-)
But whenever I select a different item in my list of items, it replaces the existing element in the array with the newly selected item. :-(
I am looking for something like below (without duplicates) which is an input to a REST endpoint -
[{ "subscriptionID" : 1234,
"isActive" : true
},
{
"subscriptionID" : 5678,
"isActive" : false
},
{
"subscriptionID" : 3489,
"isActive" : true
}]
Can someone look into where I am missing something? Or whether there is a better way I can do this?
You must declare subscriptionsArray as global variable, try this code:
var subscriptionsArray: [NSDictionary] = []
func subscriptionCell(cell: SubscriptionCell, didToggleSubscription subscription: Subscriptions) {
var subscriptionUpdateData: NSDictionary = ["subscriptionID": 0, "isActive": false]
if let matchingSubscription = subscriptionInformation?.filter({ $0.subscriptionID == subscription.subscriptionID }).first {
matchingSubscription.isActive = !(matchingSubscription.isActive!)
let subscriptionStatus = matchingSubscription.isActive
let subscriptionStatusForId = matchingSubscription.subscriptionID
subscriptionUpdateData = ["subscriptionID": subscriptionStatusForId!, "isActive": subscriptionStatus!]
tableView.reloadData()
}
subscriptionsArray.append(subscriptionUpdateData)
print("\(subscriptionsArray)")
}
You can use swift dictionary to store those unique subscriptions by using their ids as keys:
id1: status1
id2: status2
...
Code sample:
var statusesDict = [Int: Bool?]()
func subscriptionToggled(subscription: Subscription) {
if let matchingSubscription = subscriptionInformation?.filter({ $0.subscriptionID == subscription.subscriptionID }).first {
let status = matchingSubscription.isActive
let id = matchingSubscription.subscriptionID
statusesDict[id] = status
}
//if you're using the same object from dataSource array, you dont need to look for it by filtering, just use the parameter object
}
Now, when you need to send the result to server just create an array from your dictionary:
func getSubscriptionsArray() -> [[String: Any]] {
var result = [Dictionary<String, Any>]()
for (id, status) in statusesDict.enumerated() {
let subscriptionDict: [String: Any] = [
"subscriptionID" : id,
"isActive" : status
]
result.append(subscriptionDict)
}
print("\(result)")
return result
}
You should not send dictionary description as it is to server. First you should serialize it to JSON:
let jsonData = try JSONSerialization.data(withJSONObject: array, options: [])
let string = String(data: jsonData, encoding: String.Encoding.utf8)
For pretty printed json:
let jsonData = try JSONSerialization.data(withJSONObject: array, options: JSONSerialization.WritingOptions.prettyPrinted)
let string = String(data: jsonData, encoding: String.Encoding.utf8)
I have an object taken from Parse and I want to save its columns into a Dictionary or something else (if it's better).
I want to have a Dictionary like this: ["name" : "Mike", "lastname" : "vorisis", "id" : "advsas"]
Below is the code I use to take my results:
func queryEvents() {
let query = PFQuery(className: "eventController")
query.limit = 1000
query.includeKey("idEvent")
query.includeKey("eventType")
query.includeKey("idEvent.idMagazi")
query.findObjectsInBackgroundWithBlock { (objects, error)-> Void in
if let objects = objects {
for object in objects {
var post = object["idEvent"] as? PFObject
var post2 = post!["idMagazi"]
print("retrieved related post: \(post2["name"]!)")
}
}
}
}
Something else (if it's better) is a custom class.
Change the type of idMagazi to the real type.
class Event {
let post : PFObject
let name : String
let idMagazi : String
init(object : PFObject) {
self.post = object
self.name = object["name"] as! String
self.idMagazi = object["idMagazi"] as! String
}
}
And use it
...
if let objects = objects as? [PFObject] {
var events = [Event]()
for object in objects {
let post = Event(object: object)
events.append(post)
print("retrieved related post: \(post.name)")
}
}
...
In Swift Dictionary<T,V> is equivalent to [T: V]. Type is inferred if not explicitly declared.
Empty dictionary creation (all equivalent):
var dict1: Dictionary<String, String> = [:]
var dict2: [String: String] = [:]
var dict3 = Dictionary<String, String>()
var dict4 = [String: String]()
Dictionary with values (all equivalent):
var dict5 = ["Foo": "Bar", "Foo1": "Bar1", "Foo2": "Bar2"]
var dict6: Dictionary<String, String> = ["Foo": "Bar", "Foo1": "Bar1", "Foo2": "Bar2"]
var dict7: [String: String] = ["Foo": "Bar", "Foo1": "Bar1", "Foo2": "Bar2"]
Add values to an existing dictionary:
dict["Foo"] = "Bar"
In your specific scenario, you could use this:
let dict = ["name" : name, "lastname" : lastname , "id" : id]
where name, lastname and id are String variables.
Update based on your own answer:
Having this struct:
struct Event {
var nameEvent: String
var nameMagazi: String
}
You can use this approach, that avoid having an external index and uses an array instead of a dictionary for storing the results.
var events: [Event]?
guard let objects = objects else { return }
events = objects.map { object in
let post = object["idEvent"] as? PFObject
let post2 = post!["idMagazi"] as? PFObject
let nameEvent = post!["name"] as! String
let idEvent = post?.objectId
let nameMagazi = post2!["name"] as! String
return Event(nameEvent: nameEvent , nameMagazi: nameMagazi)
}
I finally found it out how can i do it.
I use a struct with what I want like this:
var userDictionary = [Int : Event]()
struct Event {
var nameEvent: String
var nameMagazi: String
}
And then i use this:
if let objects = objects {
for object in objects {
let post = object["idEvent"] as? PFObject
let post2 = post!["idMagazi"] as? PFObject
let nameEvent = post!["name"] as! String
let idEvent = post?.objectId
let nameMagazi = post2!["name"] as! String
self.events[self.i] = Event(nameEvent: nameEvent , nameMagazi: nameMagazi)
self.i += 1
}
print(self.events[1]!.nameEvent)
}
Thank you all for your answers!
Create dictionary like this:
var dict = ["name" : "Mike", "lastname" : "vorisis" , "id" : "advsas"]
OR
var dict = Dictionary<String,String>
dict.setValue("Mike", forKey: "name")
A dictionary can be made using this line:
var dictionaryArray: [Dictionary<String,String,Int>] = []
Then values can be added by appending them to the dictionary.
dictionaryArray.append(["name" : "Mike", "lastname" : "vorisis" , "id" : "advsas"])
Hope this helps.
I got the next when I'm trying to do:
for item in serverResponse {
print(item)
}
it gives me:
("0", {
"id" : 1,
"name" : "Programming"
})
("1", {
"id" : 2,
"name" : "Music"
})
How can I parse this array to take name there? I've confused with it =/
UPDATE
The full response is:
{
"name": "ABC",
"books": [
{
"id": 1,
"name": "Programming"
}
{
"id": 2,
"name": "Music"
}
]
}
You are looking to convert Json to an object to read name. Crude solution would be to parse for name. Better way of doing it is use SwiftyJson or ObjectMapper.
If you get Json from your server you can use it:
func getJSON(urlToRequest: String) -> NSData{
return NSData(contentsOfURL: NSURL(string: urlToRequest)!)!
}
func parseJSON(inputData: NSData) -> NSArray{
let boardsDictionary = try! NSJSONSerialization.JSONObjectWithData(inputData, options: .AllowFragments) as! NSArray
return boardsDictionary
}
Then use myData = parseJSON(json) and you can access name with
let data = myData[0] as! NSDictionary
let name = data["name"]! as? String
for item in serverResponse {
let itemArray = (item as? NSDictionary)["books"] as? NSArray
for (var i = 0; i < itemArray.count ; i++ ) {
if let dic1 = itemArray[i] as? NSDictionary {
let item: String!
item = dic1["name"] as? String
print(item)
}
}
}
I don't like dealing with dictionaries in Swift. I find that objects behave better and are easier to manage - they're also safer.
So my suggestion is to parse your response into "Book" structs, then you can access the properties of these structs (id, name) easily.
It could be even better to make a class that does all the work.
For testing purposes I've reproduced your response like this:
let response: NSDictionary = ["name": "ABC", "books": [["id": 1, "name": "Programming"], ["id": 2, "name": "Music"]]]
Now let's first make our Book struct.
It will have the two properties, and also an initializer which will decode the content of each dictionary that's located in the array in the "books" key of your response. The initializer is failable because the content might not be decodable.
struct Book {
let id: Int
let name: String
init?(_ object: AnyObject) {
if let dictionary = object as? NSDictionary,
dictId = dictionary["id"] as? Int,
dictName = dictionary["name"] as? String {
self.id = dictId
self.name = dictName
} else {
return nil
}
}
}
Now we can make a class that will hold all the books. We need another initializer for that, which will iterate over the contents and create the objects with the structs:
class BooksManager {
var books = [Book]()
init(response: NSDictionary) {
if let array = response["books"] as? NSArray {
self.books = array.flatMap { Book($0) }
}
}
}
Ok, now we have finished writing the boilerplate code, we can use our toys.
Create an instance of the class:
let manager = BooksManager(response: response)
That's it! Now the class holds the objects and you can easily access their properties.
For example with a loop:
for book in manager.books {
print("Book id: \(book.id), book name: \(book.name)")
}
Result:
Book id: 1, book name: Programming
Book id: 2, book name: Music
And let's say you want the name of the first book:
if let nameOfFirstBook = manager.books.first?.name {
print(nameOfFirstBook)
}
Result:
Programming
Last example, let's say you want to collect all books names in an array:
let booksNames = manager.books.map { $0.name }
Result:
["Programming", "Music"]
I am very new to programming, let alone Swift. I understand some concepts from previous attempts at programming so I have gotten further than ever before. I apologize if I am not clear in what I need.
I am pulling in JSON data of a list of alerts and I am trying to parse the data with swiftyJSON which I think is working out ok but I have run into a snag of trying to grab some data from some dictionaries within an array, and unfortunately inside a dictionary inside this arrary is where the email address is, and the different dictionaries use similar keys within each other.
I am going to show you my struct, fucntion and JSON data. Please help me grab the email address, service - its ID and its label. Also, there may be more than one Service as in the data shown and I need to capture all of them.
HERE IS THE JSON DATA:
{
"hasNext": false,
"data": [
{
"status": [
1,
"READ"
],
"resolutionStatus": [
0,
"OPEN"
],
"description": "There is some description here",
"title": "Some Activity",
"entities": [
{
"view_name": "audits",
"type": "link",
"parameters": {
"orgUnit": "/"
},
"label": "/"
},
{
"type": "user",
"id": "hidden#hidden.com",
"label": "hidden#hidden.com"
},
{
"type": "service",
"id": 6666,
"label": "someService"
},
{
"type": "service",
"id": 7777,
"label": "anotherService"
}
],
"stories": [
5
],
"date": "2014-12-10T23:46:28.067000Z",
"audits": [
"ljBhqKQVOF9w",
"pISQyT9iy9w",
"oynGf2_CIw"
],
"_id": "54fdad0dfd",
"id": [
14683,
"ALERT_SOME_ACTIVITY"
],
"severity": [
5,
"HIGH"
]
}
Here is my Struct:
struct AlertModel: Printable {
let alertUser: String?
let alertService: String?
let alertTitle: String?
let alertReadStatus: String?
let alertResolutionStatus: String?
let alertDescription: String?
let alertEntities: Array <String> = []
let alertDate: String?
let alertAudits: Array <String> = []
let alertId: String?
let
alertSeverity: String?
// change description to print to console
var description: String {
return "User: \(alertUser)\nService: \(alertService)\nTitle: \(alertTitle!)\nRead Status: \(alertReadStatus!)\nResolution Status: \(alertResolutionStatus!)\nDescription: \(alertDescription!)\nDate: \(alertDate!)\nAlert ID: \(alertId!)\nSeverity: \(alertSeverity!)\n******************************************\n"
}
init(alertUser: String?, alertService: String?, alertTitle: String?, alertReadStat
us: String?, alertResolutionStatus: String?, alertDescription: String?/*, alertEntities: Array<String>*/, alertDate: String?/*, alertAudits: Array<String>*/, alertId: String?, alertSeverity: String?) {
self.alertUser = alertUser
self.alertService = alertService
self.alertTitle = alertTitle
self.alertReadStatus = alertReadStatus
self.alertResolutionStatus = alertResolutionStatus
self.alertDescription = alertDescription
//self.alertEntities = alertEntities
self.alertDate = alertDate
//self.alertAudits = alertAudits
self.alertId = alertId
self.alertSeverity = alertSeverity
}
AND HERE IS THE FUNCTION:
let jsonAlert = JSON(data: jsonAlertObject)
if let alertArray = jsonAlert["data"].array {
var alerts = [AlertModel]()
for alertDict in alertArray {
let alertTitle: String? = alertDict["title"].stringValue
let alertReadStatus: String? = alertDict["status"][1].stringValue
let alertResolutionStatus: String? = alertDict["resolutionStatus"][1].stringValue
let alertDescription: String? = alertDict["description"].stringValue
let alertDate: String? = alertDict["date"].stringValue
let alertId: String? = alertDict["_id"].stringValue
// Need to grab the type and label from each dictionary in the array of entities
let alertEntitiesArray: Array? = alertDict["entities"].arrayObject
var arrayIndex = 0
var entitiesDict = ["" : ""]
while arrayIndex < alertEntitiesArray?.count {
entitiesDict[alertDict["entities"][arrayIndex]["type"].stringValue] = alertDict["entities"][arrayIndex]["label"].stringValue
arrayIndex++
}
let alertService: String? = entitiesDict["service"]
let alertUser: String? = entitiesDict["user"]
let alertSeverity: String? = alertDict["severity"][1].stringValue
let alert = AlertModel(alertUser: alertUser, alertService: alertService, alertTitle: alertTitle, alertReadStatus: alertReadStatus, alertResolutionStatus: alertResolutionStatus, alertDescription: alertDescription, alertDate: alertDate, alertId: alertId, alertSeverity: alertSeverity)
alerts.append(alert)
var alertsDictionaryByID = [alertId!: alert]
}
println(alerts)
}
As you can see the JSON data is a few levels deep. I have no problem getting to the data and pulling it out. The problem is the "Entities" array may not always have the same data in it. It my have multiple services, it may have no email address, it may have a completely different set of data for the first value of the array.
I am trying to get the email address out. If I could find a way to search for the "user" as with the dictionary data and then when found it would return the array index value to be able to reference it directly because I will never know with index number the user value is part of.
I hope I came across clear enough and someone can help me. --- my next step will be populating a listView with each individual alert.
I was also using SwiftyJSON, but using NSURLConnection was easy. Like this method.
//MARK: - NSURLConnection Delegate methods
var responseData : NSMutableData = NSMutableData()
func connection(connection: NSURLConnection!, didReceiveResponse response: NSURLResponse!)
{
self.responseData.length = 0
}
func connection(connection: NSURLConnection!, didReceiveData data: NSData!)
{
self.responseData.appendData(data)
}
func connectionDidFinishLoading(connection: NSURLConnection!)
{
if let responseDatas = responseData as NSData? {
if let jsonResult : NSDictionary = NSJSONSerialization.JSONObjectWithData(responseDatas, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary? {
if let dataArray = jsonResult.valueForKeyPath("data") as? NSArray
{
if let entitiesArray = dataArray.valueForKeyPath("entities") as? NSArray
{
if let firstArray = dataArray[0]
{
// access your viewName and types here
}
// Like this method, convert all your parameters and access it.
}
}
else
{
// Do something here
}
}
else
{
// Do something here
}
}
else
{
// Do something here
}
}
func connection(connection: NSURLConnection!, didFailWithError error: NSError!)
{
// Do something here
}
I ended up finding SwiftyJSON and Alamofire to significantly assist with the networking and JSON Serialization.
As far as my issue with the dictionaries within the array I ended up creating a function that iterated through the entities array looking at each dictionary seperately and then performed a Switch statement based on the key="type" to determine if it was the "user" dictionary or the "service" dictionary and then combined the 'type' value, which said if it was a user or a service, with the value of "label", which is the the username or service name, and created a new dictionary out of that which I could then reference to put back into my data model.
class func retrieveDataFromEntitiesArray (alertDict: JSON) -> (entitesDict: Dictionary<String, String>, servicesArray: [String]) {
// Need to create an array object, instead of a JSON object, of the entities array to be able to get a count to run the while against.
var arrayIndex = 0
var entitiesDict: Dictionary<String, String> = [:]
var alertEntitiesArray = alertDict.arrayObject
var servicesArray = [String]()
while arrayIndex < alertEntitiesArray?.count {
var dictKey = alertDict[arrayIndex]["type"].string
switch (dictKey!) {
case "user":
entitiesDict[alertDict[arrayIndex]["type"].stringValue] = alertDict[arrayIndex]["label"].stringValue
case "service":
servicesArray.append(alertDict[arrayIndex]["label"].stringValue)
case "policyRule":
entitiesDict[alertDict[arrayIndex]["type"].stringValue] = alertDict[arrayIndex]["label"].stringValue
default:
println("Nothing Here")
}
arrayIndex++
}
return (entitiesDict, servicesArray)
}