How To Display key and value from Json Object - ios

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]

Related

how to add Json value into model Array to display into tableview in swift

I'm using the tableview to display the Two Json value but the problem is I cant add value into model struct to displaying into tableview using two Api's. i want to show percentage value in one of the cell label and
here is my json
[
{
"Percentage": 99.792098999,
}
]
my second json value
{
"Categories": [
"Developer",
"ios "
],
"Tags": [
{
"Value": "kishore",
"Key": "Name"
},
{
"Value": "2",
"Key": "office"
},
]
}
and i need show the Categories value in Categories label in tableview
value and key on tableview
here is my Struct
struct info: Decodable {
let Categories: String?
let Tags: String?
let Value: String?
let Key: String?
var Name: String?
let percentage: Double?
}
here its my code
var List = [info]()
do {
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers)
print(json as Any)
guard let jsonArray = json as? [[String: Any]] else {
return
}
print(jsonArray)
for dic in jsonArray{
guard let per = dic["percentage"] as? Double else { return }
print(per)
}
and second json
if let array = json["Tags"] as? [[String: String]] {
for dict in array {
let key = dict["Key"]
let value = dict["Value"]
switch key {
case "office":
case "Name":
default:
break;
}
}
here is my cell for row indexpath
cell.Categories.text = list[indexpath.row].percentage
cell.Name.text = list[indexpath.row].name
cell.office.text = list[indexpath.row].office
Please use Swift 4 Codable protocol to decode the value from JSON.
//1.0 Create your structures and make it conform to Codable Protocol
struct Tags: Codable{
var Key: String
var Value: String
}
struct Sample: Codable{
var Categories: [String]
var Tags: [Tags]
}
In your method, perform below steps:
//2.0 Get your json data from your API. In example below, i am reading from a JSON file named "Sample.json"
if let path = Bundle.main.path(forResource: "Sample", ofType: "json") {
do {
let jsonData = try Data(contentsOf: URL(fileURLWithPath: path), options: .mappedIfSafe)
do {
//3.0 use JSONDecoder's decode method to decode JSON to your model.
let sample = try JSONDecoder().decode(Sample.self, from: jsonData)
//4.0 User the "sample" model to do your stuff. Example, printing some values
print("Sample.Category = \(sample.Categories)")
print("Sample.Name = \(sample.Tags[0].Value)")
print("Sample.Office = \(sample.Tags[1].Value)")
} catch let error {
print("Error = \(error)")
}
} catch {
// handle error
}
}
I prefer to use Codable all the time with JSON even for simpler types so for percentage I would do
struct ItemElement: Decodable {
let percentage: Double
enum CodingKeys: String, CodingKey {
case percentage = "Percentage"
}
}
and we need to keep these values in a separate array, declared as a class property
let percentageList: [Double]()
and json encoding would then be
let decoder = JSONDecoder()
do {
let result = try decoder.decode([ItemElement].self, from: data)
percentageList = result.map { item.percentage }
} catch {
print(error)
}
Similar for the second part
struct Item: Decodable {
let categories: [String]
let tags: [Tag]
enum CodingKeys: String, CodingKey {
case categories = "Categories"
case tags = "Tags"
}
}
struct Tag: Decodable {
let value, key: String
enum CodingKeys: String, CodingKey {
case value = "Value"
case key = "Key"
}
}
use a dictionary for the result, again as a class property
var values = [String: String]()
and the decoding
let decoder = JSONDecoder()
do {
let result = try decoder.decode(Item.self, from: data)
for item in result.tags {
values[item.key] = values.item.value
}
} catch {
print(error)
}
and then in the cell for row code
cell.Categories.text = percentageList[indexpath.row].percentage
cell.Name.text = values["name"]
cell.office.text = values["office"]
Note that this last code looks very strange since you don't have an array of name/office values judging by your json. Maybe you have simplified it some way but the code above is the best I can do with the information given even if it possibly wrong

I am unable to pass data from model class to table view in swift 3?

In this I am getting data from server response after posting parameters and here I need to display it on table view and it should be displayed like shown below in the image 0 is the price for the particular shipping method
already i had written model class for server response data and here it is
struct ShippingMethod {
let carrierCode : String
let priceInclTax : Int
let priceExclTax : Int
let available : Any
let carrierTitle : String
let baseAmount : Int
let methodTitle : String
let amount : Int
let methodCode : String
let errorMessage : Any
init(dict : [String:Any]) {
self.carrierCode = dict["carrier_code"] as! String
self.priceInclTax = dict["price_incl_tax"]! as! Int
self.priceExclTax = dict["price_excl_tax"]! as! Int
self.available = dict["available"]!
self.carrierTitle = dict["carrier_title"] as! String
self.baseAmount = dict["base_amount"]! as! Int
self.methodTitle = dict["method_title"]! as! String
self.amount = dict["amount"]! as! Int
self.methodCode = dict["method_code"] as! String
self.errorMessage = (dict["error_message"] != nil)
}
}
by using this I had formed an array type like this by using code
var finalDict = [String: [String]]()
var responseData = [ShippingMethod]()
do
{
let array = try JSONSerialization.jsonObject(with: data, options: []) as? [[String : Any]]
for item in array! {
self.responseData.append(ShippingMethod.init(dict: item))
}
print(self.responseData)
}
catch let error
{
print("json error:", error)
}
print(self.responseData)
for item in self.responseData {
let dict = item
let carrierTitle = dict.carrierTitle
let methodTitle = dict.methodTitle
if self.finalDict[carrierTitle] == nil {
self.finalDict[carrierTitle] = [String]()
}
self.finalDict[carrierTitle]!.append(methodTitle)
}
print(self.finalDict)
the output of this finalDict is ["Flat Rate": ["Fixed"], "Best Way": ["Table Rate"]] in this carrier title key value pair should be displayed as section title and is Flat Rate and method title key value pair should be displayed as rows in section Fixed but the problem is I need amount key value pair with it also for corresponding method title can anyone help me how to get this ?
Why don't you create another struct for displaying row data:
struct CarrierInfo {
let name:String
let amount:Int
}
Change your finalDict to
var finalDict = [String: [CarrierInfo]]()
and create CarrierInfo instance and set it in finalDict
for item in self.responseData {
let dict = item
let carrierTitle = dict.carrierTitle
let methodTitle = dict.methodTitle
let amount = dict.amount
if self.finalDict[carrierTitle] == nil {
self.finalDict[carrierTitle] = [CarrierInfo]()
}
self.finalDict[carrierTitle]!.append(CarrierInfo(name: carrierTitle, amount: amount))
}
Likewise you can make other required changes. This would neatly wrap your row display data inside a structure.
PS: I have not tested the code in IDE so it may contain typos.
You can assign another dictionary with key as methodTitle and amount as value. i.e., ["fixed":"whatever_amount"]
OR
You can use finalDict differently, like ["Flat Rate": ["tilte":"Fixed","amount":"0"], "Best Way": ["title":"Table Rate","amount":"0"]]
If it is difficult for you to code this, you can revert back.
Edit
You can use the following code to create the array in the second solution I suggested above:
for item in self.responseData {
let dict = item
let carrierTitle = dict.carrierTitle
let methodTitle = dict.methodTitle
let amount = dict.amount
if self.finalDict[carrierTitle] == nil {
self.finalDict[carrierTitle] = [[String:String]]()
}
let innerDict = ["title":methodTitle,"amount":amount]
self.finalDict[carrierTitle]!.append(innerDict)
}

How do i parse JSON, sort it in an array. Pull out the data and populate to a tableview?

i am trying to parse JSON into an array. Sort it according the highest appointment made. And then use that new array to populate it on leaderboard tableview.
I am using SwiftJson
Stuck on sorting into array
Would need to populate Name and the rest of the values in tableview in descending order.
Here are my snippets.
let jsonUrl = URL(string: url)
URLSession.shared.dataTask(with: jsonUrl!) { (data, response, error) in
guard let data = data else { return }
let jsonResult : JSON = JSON(data)
print(jsonResult)
} .resume()
Here are the output
{
"Activities" : {
"AHiHr9bzGXcN7pxvR68wulD9zqE3" : {
"Case Closed" : "2",
"Name" : "Tim Mac",
"Appointment Made" : "2",
"Prospects Met" : "2",
"Policy Servicing" : "2"
},
"gDKBlbeMsiUUFaASOLn6eOdCIrJ3" : {
"Case Closed" : "1",
"Name" : "Jane Simpson",
"Appointment Made" : "1",
"Prospects Met" : "1",
"Policy Servicing" : "1"
},
"W8uWoLf9qRX4a9BgXjLw5VZXjFu1" : {
"Case Closed" : "3",
"Name" : "John Doe",
"Appointment Made" : "4",
"Prospects Met" : "3",
"Policy Servicing" : "2"
}
}
}
you can get all values as Array of Dictionary and Sort it Like :
guard let Activities = jsonResult?["Activities"] as? [String:AnyObject] else {
return
}
var values = [Dictionary<String, AnyObject>]()
for (_, value) in Activities {
values.append(value as! Dictionary<String, AnyObject>)
}
let sorted = values.sorted { (dic1, dic2) -> Bool in
Int(dic1["Appointment Made"] as? String ?? "") ?? 0 > Int(dic2["Appointment Made"] as? String ?? "") ?? 0
}
print(sorted)
// model your data
for item in sorted {
let model = Model.init(jsonData: item)
// use model
}
// your model
class Model: NSObject {
var caseClosed :Int?
var name :String?
var appointmentMade :Int?
var prospectsMet :Int?
var policyServicing :Int?
override init() {
super.init()
}
init(jsonData : [String:AnyObject]) {
// map data to object
}
}
Use JsonSerialisation jsonObjectWithData to convert jSon response to NSArray object. And run a for loop, access every element in array as NSDictionary and compare their values for highest appointment.
To know more about accessing values from NSDictionary, apple docs reference
To know more about working with json in swift, apple docs reference.
I have tried this sorting:
let activitiesDict = jsonData?["Activities"] as? [String:Any]
let activitiesArray = activitiesDict.map({ [$0.0 : $0.1] })
let sortedActivitiesArray = self.activitiesArray.sorted {
(Int((($0 as! Dictionary<String, Any>)["Appointment Made"] as? String)!))! > (Int((($1 as! Dictionary<String, Any>)["Appointment Made"] as? String)!))!
}
print(sortedActivitiesArray)
Hope it helps.

how to create json object in ios swift

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)

Making a Dictionary in Swift

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.

Resources