swift - JSON dictionary parsing - json

I have a JSON file like below, I want to parse it and populate my tableview.
What I want to get is "material", "categories", "product_types"
["facets": {
"material" : {
"data" : [
{
"count" : 3,
"value" : "95% Polyester, 5% Spandex"
},
{
"count" : 1,
"value" : "%100 Modal"
}
],
},
"categories" : {
"data" : [
{
"id" : "7",
"name" : "test"
}
],
},
"product_types" : {
"data" : [
{
"count" : 3,
"value" : "Sweatshirt"
},
{
"count" : 1,
"value" : "Babet"
},
],
}
}]
My code is:
var list: [String:JSON]? = [:]
func loadList(){
ModafiliAPI.sharedInstance.refine(callback: { (refineList) in
if let data = refineList["facets"].dictionaryValue as [String:JSON]?{
self.list = data
self.RefineTableView!.reloadData()
print(self.refineList!)
}
})
}
I observe that I can access "facets" from the print output. But in cellforrowat
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "RefineCell") as! RefineTableViewCell
cell.refineList = self.refineList?[indexPath.row] //-->>error
return cell
}
I am getting the following error: Ambiguous reference to member 'subscript'
UITableViewCell:
var refineList:[String:JSON]?{
didSet{
self.setupRefineList()
}
}

Xcode doesn't know what type is refineList, it's ambiguous for him
try
cell.refineList = self.refineList?[indexPath.row] as! [String:JSON]
You may also check what cell.refineList type ?
Also try:
guard let list = refineList?[indexPath.row] else {
print ("Unexpected error !!")
return cell
}
cell.refineList:[String:JSON] = list as! [String:JSON]

Related

Fill TableSection from Json Response in Swift

How to Populate TableSections with from this JSON Response.
I have implemented the design like the dropdown and having one prototype cell with two labels side by side inside it. below is the structure of my design
StudentDetailsSection V(button)
Father'sDetailsSection V(button)
Mother'sDeatilsSection V(button)
I am also attaching the screenshot of my design
My JSON Response is in structure.
{
"Student_Details":
[
{
"Student_ID": 1,
"School_ID": 1,
"FirstName": "Ammu",
"LastName": "Gopal",
"Date_Of_Birth": "2017-08-05T00:00:00",
"Gender": 1,
"Class": " LKG ",
"Section": "A",
"Mother_Tongue": "Tamil",
"Blood_Group": 1,
"Place_Of_Birth": "Chennai",
"Caste": 1,
"Religion": 1,
"Special_Person": 1,
"Languages_Known": "English,Tamil,Hindi",
"Distance_From_Residence_To_School": "11",
"Nationality": "Indian",
"Mode_Of_Transport": "School Transport",
"RTE": null,
"StudentStatus": 1,
"AppliedStatus": null,
"IsDeleted": null,
"Father_Name": "Kannan",
"Father_Mobile": "9845245254",
"Father_Email": "kannan#gmail.com",
"Father_Education": "Bsc",
"Father_Occupation": "Self-employer",
"Father_Name_Of_The_Organisation": "Bussiness",
"Father_Designation": "Self-Employer",
"Father_Annual_Income": "200000",
"Father_Office_Or_Business_Address": null,
"Mother_Name": "Mathi",
"Mother_Mobile": "9845245145",
"Mother_Email": "mathi#gmail.com",
"Mother_Education": "B com",
"Mother_Occupation": "Self Employer",
"Mother_Name_Of_The_Organisation": "Self Employer",
"Mother_Designation": "Self Employer",
"Mother_Annual_Income": "200000",
"Mother_Office_Or_Business_Address": null,
"Sibling_Details": null,
"Land_Line_Number": "044-2121444",
"Guardian_Name": null,
"Guardian_Mobile": null,
"Guardian_Email": null,
"Relationship": null,
"Guardian_Education": null,
"Guardian_Occupation": null,
"Guardian_Name_Of_The_Organisation": null,
"Guardian_Designation": null,
"Guardian_Annual_Income": null,
"Guardian_Office_Or_Business_Address": null,
"Guardian_Land_Line_Number": null,
"LeaveLetterApplied": null,
"Message": null,
"Date": null,
"Notify": null,
"Status": null
}
]
}
how to fetch data from this jsonresponse and fill the particular section.Hoping for the help.Thanks in advance.
Consider you have static 3 sections:
1) Its a good habit to declare constants.
let SEC_STUDENT = 0
let SEC_FATHER = 1
let SEC_MOTHER = 2
2) Get array from response
enum Student_Key : String
{
case ID = "Student_ID"
case FirstName = "FirstName"
case LastName = "LastName"
//Define all keys so on
}
enum Father_Key : String
{
case Name = "Father_Name"
case Mobile = "Father_Mobile"
//Define all keys so on
}
enum Mother_Key : String
{
case Name = "Mother_Name"
case Mobile = "Mother_Mobile"
//Define all keys so on
}
//Define global
var arrStudent : Array<[String:String]> = []
var arrMother : Array<[String:String]> = []
var arrFather : Array<[String:String]> = []
//Add new method to parse response
func parseData(response : [String:Any]) {
let arrayData = response["Student_Details"] as! [Any]
//You can load only one record in your current way.
let studentData = arrayData[0] as! [String:Any]
arrStudent.append(["key":Student_Key.ID.rawValue ,
"value" : String(describing: studentData[Student_Key.ID.rawValue])])
arrStudent.append(["key":Student_Key.FirstName.rawValue,
"value": String(describing: studentData[Student_Key.FirstName.rawValue])])
arrStudent.append(["key":Student_Key.LastName.rawValue,
"value": String(describing: studentData[Student_Key.LastName.rawValue])])
//You have to add all keys mannualy
arrMother.append(["key":Father_Key.Name.rawValue,
"value": String(describing: studentData[Father_Key.Name.rawValue])])
arrMother.append(["key":Father_Key.Mobile.rawValue,
"value": String(describing: studentData[Father_Key.Mobile.rawValue])])
arrFather.append(["key":Mother_Key.Name.rawValue,
"value": String(describing: studentData[Mother_Key.Name.rawValue])])
arrFather.append(["key":Mother_Key.Mobile.rawValue,
"value": String(describing: studentData[Mother_Key.Mobile.rawValue])])
yourTable.reloadData()
}
3) Return section, which you already implemented.
4) Return number of rows
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if indexPath.section == SEC_STUDENT
{
return arrStudent.count
}
else if indexPath.Section == SEC_FATHER
{
return arrFather.count
}
else if indexPath.Section == SEC_MOTHER
{
return arrMother.count
}
else {
return 0
}
}
5) Load cell for index
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "YourCellIdentifier") as! YourCell
let dictData : [String:Any]
if indexPath.section == SEC_STUDENT
{
dictData = arrStudent[indexPath.row] as! [String:Any]
}
else if indexPath.Section == SEC_FATHER
{
dictData = arrFather[indexPath.row] as! [String:Any]
}
else if indexPath.Section == SEC_MOTHER
{
dictData = arrayData[indexPath.row] as! [String:Any]
}
cell.lblKey = data["key"]
cell.lblValue = data["value"]
return cell
}
** Notes
1) It may be your requirement but this is not a correct way to handle and show json.
2) Currently you can only show on student record then it should be detail page of student.
3) I just typed code to show way to achieve your goal. You have to handle things in your code.

Repeated values in UITable cells from api json

After I do http call from api I get json file then I loop through it to get specific values:
if let value: AnyObject = response.result.value as AnyObject? {
let json = JSON(value)
for (key, subJson) in json {
let drivers = subJson["driver"]
for (key, subJson) in drivers {
let status = subJson["status"].stringValue
let date = subJson["created_at"].stringValue
let name = subJson["name"].stringValue
let pivot = subJson["pivot"]
for (key, subJson) in subJson["pivot"] {
let type = pivot["type"].stringValue
let data = Driverj(name: name, status: status, created_at: date)
self.data.append(data)
}
DispatchQueue.main.async {
self.tableview.reloadData()
}
}
}
}
in a separate file I connect the values with objects:
class DriverC: UITableViewCell {
#IBOutlet weak var status : UILabel!
#IBOutlet weak var date : UILabel!
#IBOutlet weak var job : UILabel!
#IBOutlet weak var update : UILabel!
}
And in another file I have the data saved :
import Foundation
import ObjectMapper
class Driverj : Mappable {
var status : String?
var name : String?
var created_at : String?
required init?(map: Map) {
}
required init(name: String , status : String , created_at : String ) {
self.status = status
self.name = name
self.created_at = created_at
}
func mapping(map: Map) {
status <- map["status"]
name <- map["name"]
created_at <- map["created_at"]
}
}
And finally here is how it's displayed
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "DriverCell", for: indexPath) as! DriverC
let entry = data[indexPath.row]
cell.date.text = entry.date
cell.job.text = entry.job
cell.status.text = entry.status
cell.update.text = entry.name
return cell
}
My question is when I run my project I get three cells with the same data repeated. Why ?
the json files :
[
{
"id": 4,
"name": null,
"email": "5#5.com",
"status": 0,
"confirmed": false,
"street": "street ",
"niehgborhood": "North",
"city": "Sf",
"national_id": "1009090",
"phone": "9000",
"size_of_house": null,
"created_at": "2016-12-04 13:55:52",
"updated_at": "2017-03-08 14:03:44",
"deleted_at": null,
"driver": [
{
"name": "unknown",
"age": "25",
"Smoker": "No",
"language": "English",
"religion": "Muslim",
"created_at": null,
"updated_at": "2017-03-08 13:48:55",
"status": "تم",
"pic": "http://localhost:8000/images/1488714520.jpg",
"id": 1,
"pivot": {
"user_id": 4,
"driver_id": 1,
"type": "driver"
}
},
{
"name": "Jae",
"age": "30",
"Smoker": "No",
"language": "English",
"religion": "Muslim ",
"created_at": "2017-02-28 09:36:15",
"updated_at": "2017-03-08 08:46:06",
"status": "ok",
"pic": "http://localhost:8000/images/1488714520.jpg",
"id": 2,
"pivot": {
"user_id": 4,
"driver_id": 2,
"type": "driver"

Parse JSON from GoogleApiBooks

I'm trying to parse this JSON but it don't works.
This is the JSON:
{
"kind": "books#volumes",
"totalItems": 1,
"items": [
{
"kind": "books#volume",
"id": "uCHmPQAACAAJ",
"etag": "aBZ3KnoRsq4",
"selfLink": "https://www.googleapis.com/books/v1/volumes/uCHmPQAACAAJ",
"volumeInfo": {
"title": "Psicologia delle folle",
"authors": [
"Gustave Le Bon"
],
"publishedDate": "2004",
"industryIdentifiers": [
{
"type": "ISBN_10",
"identifier": "8850206240"
},
{
"type": "ISBN_13",
"identifier": "9788850206247"
}
],
"readingModes": {
"text": false,
"image": false
},
"pageCount": 251,
"printType": "BOOK",
"categories": [
"Psychology"
],
"maturityRating": "NOT_MATURE",
"allowAnonLogging": false,
"contentVersion": "preview-1.0.0",
"language": "it",
},
"saleInfo": {
"country": "IT",
"saleability": "NOT_FOR_SALE",
"isEbook": false
},
"accessInfo": {
"country": "IT",
"viewability": "NO_PAGES",
"embeddable": false,
"publicDomain": false,
"textToSpeechPermission": "ALLOWED",
"epub": {
"isAvailable": false
},
"pdf": {
"isAvailable": false
},
,
"accessViewStatus": "NONE",
"quoteSharingAllowed": false
}
}
]
}
And this is the code that i'm using:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
var url = "https://www.googleapis.com/books/v1/volumes?q=isbn9788850206247&key=my-key"
Alamofire.request(url).responseJSON { (responseData) -> Void in
if((responseData.result.value) != nil) {
let swiftyJsonVar = JSON(responseData.result.value!)
if let resData = swiftyJsonVar["items"].arrayObject {
self.arrRes = resData as! [[String:AnyObject]]
print(self.arrRes)
}
if self.arrRes.count > 0 {
self.tableProva.reloadData()
}
}
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableProva.dequeueReusableCell(withIdentifier: "cellProva", for: indexPath) as! CellProvaClass
var dict = arrRes[indexPath.row]
cell.titleLabel?.text = dict["title"] as? String
cell.authorLabel?.text = dict["authors"] as? String
return cell
}
How can I solve this problem?
This is your JSON Reponse ( in short format) :
And this is the data structure (Array and dictionary format) :
Now you have to access : title and authors so here is your value in cellforRowAtIndexPath Method , a dictionary having name dict stores values of volumeInfo ( a Dictionary) :
so you have to use this way to access title :
cell.titleLabel?.text = dict["volumeInfo"]["title"] as? String
//To Fetch Author array
if let authorArray = dict["volumeInfo"]["authors"] as? NSArray{
print(authorArray)
}
and then to access author is an array so which index of value you want to show in cell.authorLabel .
In Second Screenshot those which are enclosed with {} is Dictionary and [] is Array
First try to show Title and then same way try to fetch value of author array and set according to your requirement.
Feel Free to comment if any further issue.
When you are parsing the JSON on line
if let resData = swiftyJsonVar["items"].arrayObject {
you will receive an object of NSDictionary which contains all other nested elements & arrays in keys. In your tableView delegate you are directly accessing the value from arrRes by unboxing it to NSDictionary object. All the entries are available in an array named items which further has a nested object volumeInfo which contains the info about title & another array of Authors.
You need to extract the further nested objects from arrRes object to use it in your tableView cellForRowAtIndex delegate function.
Let me know if you need any further help.

How to get this subJson using SwiftyJSON?

"groups" : {
"232" : {
"name" : "John",
"age" : "22"
}
},
"143" : {
"name" : "Dylan",
"age" : "22"
}
}
How to get "name" using swiftyJSON? I got the id value but ["name"]'s always nil with this code:
for (results,subJson):(String, JSON) in json["groups"] {
let id = results
print(id) //--> 232
let name = subJson["\(id)"]["name"].string
print(name) //--> nil
}
The name key is inside subJson, remove the id subscript:
for (id, subJson):(String, JSON) in json["groups"] {
print(id)
if let name = subJson["name"].string {
print(name)
}
}

How can I store data in global variable out side Alamofire in Swift

I did try to get data from web services which is Dictionary data type by using librar which are Alamofire and SwiftJSON. My problem is I cannot store data in global variable which is outside the Alamofire.
Here are my codes.
var productsAll:JSON = []
override func viewDidLoad() {
super.viewDidLoad()
Alamofire.request(.GET, url).responseJSON {
(request, response, json, error) in
if json != nil {
var jsonObj = JSON(json!)
var data = jsonObj["product"].dictionaryObject
self.productsAll = JSON(data!)
println("out form in side \(self.productsAll)")
}
}
}
When I println productAll inside viewDidLoad() I get Json data type.
out form in side {
"tax_class" : "",
"related_ids" : [
],
"on_sale" : false,
"taxable" : false,
"variations" : [
],
"description" : "<p><b id=\"mf528\">ZALORA<\/b> <\/p>\n",
"average_rating" : "0.00",
"managing_stock" : false,
"shipping_class_id" : null,
"backorders_allowed" : false,
"id" : 4636,
]
]
]
}
}
But when I println productAll somewhere else out side viewDidLoad. I get nothing.
[
]
How can I store data productAll in Alamofire to global variable
var productsAll:JSON = []
Thank you.