Parsin JSON directory inside another directory - ios

Alamofire.request("https://example.com/stories.php", method: .post, parameters: parameters).validate().responseJSON { response in
switch response.result {
case .success:
if let json = response.result.value {
let json2 = JSON(json)
for (_, subJSON): (String, JSON) in json2[0]["stories"] {
if let arr = subJSON["user"].dictionary {
let title = arr["name"]?.string
let id = arr["id"]?.int
let photo = arr["picture"]?.string
let rel1 = InboxStories(title: title!, storyID: id!, photo:photo!)
cell.arrayOfRels.append(rel1)
}
}
cell.getStoryDel()
}
case .failure(_):
print("hata")
}
}
JSON output
[{
"stories": [{
"id": "s1",
"last_updated": "1582543824",
"user": {
"id": "2",
"name": "testuser",
"picture": "https:\/\/example.com\/ios\/images\/profile_pic\/116534.jpg"
},
"snaps_count": "1",
"snaps": [{
"id": "c1",
"mime_type": "image",
"url": "chttps:\/\/example.com\/ios\/stories\/image\/3434.jpg",
"last_updated": "1582543824"
}]
}],
"count": 1
}]
I am trying to reach user key of stories.
It returns nil in my code. How can I parse it?

stories is also an array, please note the []
And it's pretty confusing to name a dictionary arr 😉
if let stories = json2.array?.first?["stories"].array {
for story in stories {
if let dict = story["user"].dictionary {
let title = dict["name"]!.stringValue
let id = dict["id"]!.stringValue
let photo = dict["picture"]!.stringValue
let rel1 = InboxStories(title: title, storyID: id, photo:photo)
cell.arrayOfRels.append(rel1)
}
}
}
And consider to use Decodable. It's built-in and more comfortable than SwiftyJSON

Related

How to parse json data include page number by codable in Swift 4 and Alamofire

I'm a new with Swift and I'm confusing to get data instead of using SwiftyJson by using Codable.
The format Json data type like as:
{
"current_page": 1,
"total_page": 407,
"new_entries": [
{
"id": 10174,
"title": "Hello",
"description": "Hello",
"categories": "women",
"image": "imagelink",
"url": "urllink",
"date": "time",
"is_favorite": false
},
{
"id": 9237,
"title": "hi",
"description": "hi",
"categories": "skincare",
"image": "imagelink",
"url": "url",
"date": "time",
"is_favorite": false
},
So how do I get the entries and decode and save to codable like
let decoder = JSONDecoder()
do {
let feed = try decoder.decode(Feed.self, from: jsonData)
print(feed.title)
} catch {
print(error.localizedDescription)
}
I stop at this below and dont know how to convert the json["new_entries"] to string type and decode.
Alamofire.request("https://abc.jp/api/category/women_all/?page=1", method: .get, parameters: nil, encoding: JSONEncoding.default, headers: nil).responseJSON { (response:DataResponse<Any>) in
debugPrint(response)
if let JSON = response.result.value as? NSDictionary {
GlobalVariables.sharedManager.pageCurr = JSON["current_page"] as? Int
GlobalVariables.sharedManager.pageTotal = JSON["total_page"] as? Int
if let entries = JSON["new_entries"] as? NSArray{
for entry in entries {
if let entry = entry as? NSDictionary {
for (key, value) in entry {
print("\(key) - \(value)")
}
}
}
}
}
My Feed Struct
struct Feed: Codable {
enum CodingKeys: String, CodingKey {
case id
case title
case description
case categories
case image
case url
case date
case favorite = "is_favorite"
}
let id: Int
let title: String
let description: String
let categories: String
let image: String
let url: String
let date: String
let favorite: Bool
}
Thanks so much.
You need
struct Root: Codable {
let currentPage, totalPage: Int
let newEntries: [Feed]
}
struct Feed: Codable {
let id: Int
let title, description, categories, image: String
let url, date: String
}
Alamofire.request("https://abc.jp/api/category/women_all/?page=1", method: .get, parameters: nil, encoding: JSONEncoding.default, headers: nil).responseData { response in
debugPrint(response)
guard let data = response.data else { return }
do {
let de = JSONDecoder()
de.keyDecodingStrategy = .convertFromSnakeCase
let res = try de.decode(Root.self, from: data)
print(res.currentPage)
print(res.totalPage)
print(res.newEntries)
}
catch {
print(error)
}
}
correct json
{
"current_page": 1,
"total_page": 407,
"new_entries": [
{
"id": 10174,
"title": "Hello",
"description": "Hello",
"categories": "women",
"image": "imagelink",
"url": "urllink",
"date": "time",
"is_favorite": false
},
{
"id": 9237,
"title": "hi",
"description": "hi",
"categories": "skincare",
"image": "imagelink",
"url": "url",
"date": "time",
"is_favorite": false
}]
}
I added a new main struct
struct Main: Codable {
let currentPage: Int
let totalPage: Int
let feeds: [Feed]
enum CodingKeys: String, CodingKey {
case currentPage = "current_page"
case totalPage = "total_page"
case feeds = "new_entries"
}
}
and then decode using that struct
let decoder = JSONDecoder()
do {
let result = try decoder.decode(Main.self, from: jsonData)
print(result.currentPage)
} catch {
print(error)
}
or with the alamofire example
Alamofire.request("https://abc.jp/api/category/women_all/?page=1", method: .get, parameters: nil, encoding: JSONEncoding.default, headers: nil).responseData { response in
guard let data = response.data else { return }
do {
let decoder = JSONDecoder()
let result = try decoder.decode(Main.self, from: data)
GlobalVariables.sharedManager.pageCurr = result.currentPage
GlobalVariables.sharedManager.pageTotal = result.totalPage
for feed in result.feeds {
print(feed.id)
//etc
}
} catch {
print(error)
// other error handling
}

How to parsed all the data in JSON?

First issue I addressed
I am working on an APIService using Alamofire, I tried to print the response and the I got the data successfully, but unfortunately the data from JSON turns to nil when I parse it to the attendees Object. How can I reflect the data from json to the attendees object?
Second Issue
I solved the 1st issue, after all the debugging I had. The codes I used was written in my answer below. I parsed data from JSON going to attendees but as I checked only the first array was fetch. How can I get all the data inside the JSON? Hope you can help me. Thank you.
func getParticipants(passcode: String,
participantType: ParticipantType,
successBlock: #escaping (Attendees?) -> Void,
failureBlock: #escaping (Error) -> Void)
{
let attendeesURL = URL(string: "\(GET_PARTICIPANTS_URL)/\(passcode)/\(participantType)")
Alamofire.request(attendeesURL!, method: .get).responseJSON { (response) in
print(response)
if let error = response.error
{
failureBlock(error)
return
}
if let attendeeJSON = response.result.value as? [Dictionary<String, Any>],
let attendeeObj = attendeeJSON.first {
print(attendeeObj)
let attendees = Attendees.init(JSON: attendeeObj)
successBlock(attendees)
}
}
}
}
JSON
[
{
"event_name": "Laugh Trip",
"event_participants": [
{
"participant_id": "6f1e7fd5-6da9-4d5b-bc91-4771aeaa5235",
"employee_number": "",
"last_name": "name",
"first_name": "name",
"middle_name": "",
"display_name": "name, name ",
"department_name": "IT",
"position_name": "Application Developer",
"registered_flag": true,
"registered_datetime": "2018-07-16T14:51:57.813",
"registration_type": 1,
"delete_flag": false,
"manual_reg_flag": false,
"out_flag": true,
"out_datetime": "2018-07-16T14:54:00.000",
"classification": 1,
"others": ""
},
{
"participant_id": "6f1e7fd5-6da9-4d5b-bc91-4771aeaa5235",
"employee_number": "",
"last_name": "name",
"first_name": "name",
"middle_name": "",
"display_name": "name, name ",
"department_name": "IT",
"position_name": "Application Developer",
"registered_flag": true,
"registered_datetime": "2018-07-16T14:51:57.813",
"registration_type": 1,
"delete_flag": false,
"manual_reg_flag": false,
"out_flag": true,
"out_datetime": "2018-07-16T14:54:00.000",
"classification": 1,
"others": ""
},
]
]
Instead of using first which gets only the first item of the sequence use a loop respectively.
if let events = response.result.value as? [[String : Any]] {
for event in events {
if let eventparticipants = event["event_participants"] as? [[String : Any]] {
print(eventparticipants)
for participant in eventparticipants {
let attendees = Attendees.init(JSON: participant)
successBlock(attendees)
}
}
}
}
I recommend to decode the JSON directly into structs with Decodable
I solved my own issue. :D
Alamofire.request(attendeesURL!, method: .get).responseJSON { (response) in
print(response)
if let error = response.error
{
failureBlock(error)
return
}
if let jsonDictionary = response.result.value as? [Dictionary<String, Any>]{
if let eventparticipants = jsonDictionary.first {
print(eventparticipants)
if let partObj = eventparticipants["event_participants"] as? [[String : Any]]{
let attendeeObj = partObj.first
let attendees = Attendees.init(JSON: attendeeObj!)
successBlock(attendees)
}
}
}
}

swift getting all values of a dictionary and passing to viewcontroller using almaofire

Hi have an application which collects data from an api and I use Alamofire and swiftyJSON. the current challenge I am facing now is that I have different dictionaries in one array and I want to be able to retun back specific items in the dictionary. this is the array I am working with
Json
[
{
"images": [
{
"id": 8,
"original": "http://127.0.0.1:8000/media/images/products/2018/05/f3.jpg",
"caption": "",
"display_order": 0,
"date_created": "2018-05-26T17:24:34.762848Z",
"product": 13
},
{
"id": 9,
"original": "http://127.0.0.1:8000/media/images/products/2018/05/f5.jpg",
"caption": "",
"display_order": 1,
"date_created": "2018-05-26T17:24:34.815214Z",
"product": 13
},
{
"id": 10,
"original": "http://127.0.0.1:8000/media/images/products/2018/05/f2.jpg",
"caption": "",
"display_order": 2,
"date_created": "2018-05-26T17:25:19.117271Z",
"product": 13
},
{
"id": 11,
"original": "http://127.0.0.1:8000/media/images/products/2018/05/f4.jpg",
"caption": "",
"display_order": 3,
"date_created": "2018-05-26T17:25:19.155159Z",
"product": 13
}
]
}
]
get a single image is like this
Alamofire.request(URL, method: .get, parameters: nil, encoding: JSONEncoding.default, headers: HEADER).responseJSON { (response) in
if response.result.error == nil {
guard let data = response.data else {return}
do {
if let json = try JSON(data: data).array {
for item in json {
let images = item["images"][0]["original"].stringValue
....
this returns only the indexed image.[0] if it is set to [1] it returns the indexed image at 1.
how do I return all the images so that I can loop through all and display in a collection view controller. more codes would be supplied on request.
You can dit it Like that :
if let json = try? JSON(data: data).arrayValue {
for item in json {
let imagesList = item["images"].arrayValue
let imagesURL = imagesList.map {$0["original"].string}.compactMap({$0})
if imagesURL.count > 0{
print( imagesURL[0])
}
}
}
Or:
do {
let json = try JSON(data: data).array
json?.forEach({ (item) in
let imagesList = item["images"].arrayValue
let imagesURL = imagesList.map {$0["original"].string}.compactMap({$0})
if imagesURL.count > 0{
print( imagesURL[0])
}
})
} catch {
print(error.localizedDescription)
}

swift parsing desc and parsing selected element

Swift parsing desc and parsing selected element. I want to parse desc and after parsing desc parse desc content. thanks swift parsing desc and parsing selected element.
I have tried different methods. Does anyone have an idea on how we can make it possible? I tried the following code:
**Code for getting the data**
func demoApi1() {
Alamofire.request("", method: .get, parameters: nil, encoding: JSONEncoding.default, headers: nil).responseJSON { (response:DataResponse<Any>) in
switch(response.result) {
case .success(_):
guard let json = response.result.value as! [[String:Any]]? else{ return}
print("Ang Response: , \(json)")
for item in json {
self.getAllDetail.append(item )
if let desc = item["dec"] as? String {
self.titleArray.append(desc)
print("motherfucker:" , self.titleArray)
}
}
if !self.getAllDetail.isEmpty{
DispatchQueue.main.async {
}
}
break
case .failure(_):
print("Error")
break
}
}
}
Response:
Ang Response [["status": {
name = ongoing;
}, "sched": 2018-04-10T14:22:00+08:00, "desc": asdasdasdsa, "id": 224, "reward": 1.00, "parent": das, "child": dasdas, "date_created": 2018-04-19T15:54:24.657644+08:00, "name": sad, "occurrence": {
name = once;
}, "type": , "date_modified": 2018-04-19T15:54:24.703520+08:00], ["status": {
name = ongoing;
}, "sched": 2018-04-19T15:54:24.657644+08:00, "desc": {
"questions" : [
{
"b" : 2,
"a" : 1
},
{
"b" : 3,
"a" : 2
},
{
"b" : 2,
"a" : 8
},
{
"b" : 9,
"a" : 7
},
{
"b" : 3,
"a" : 6
}
],
"operation" : "addition"
}, "id": 226, "reward": 1.00, "parent": shit, "child": , "date_created": 2018-04-23T14:16:35.739436+08:00, "name": chorename, "occurrence": {
name = once;
}, "type": homework, "date_modified": 2018-04-23T14:16:35.790237+08:00]]
String to Dictionary:
func stringToDictionary(_ strToJSON : String)-> [String:Any]{
print("JsonString:\(strToJSON)")
let data = strToJSON.data(using: .utf8)
var dict = [String:Any]()
do {
dict = try JSONSerialization.jsonObject(with: data!) as! [String:Any]
return dict
}
catch let error as NSError {
print("Error is:\(error)")
}
return dict
}
Use it like this:
let dictConv = stringToDictionary("your_string")
print(dictConv)

How to loop through JSON data in SwiftyJSON

I have a JSON data with structure and I don't know how to use for-loop with SwiftyJSON to get each sections entries of "path" and "updated" value. Anyone can help? Thanks.
var jsonData = "{
"css":[
{
"path": "style.css",
"updated": "12432"
},
{
"path": "base.css",
"updated": "34627"
},
],
"html":[
{
"path": "home.htm",
"updated": "3223"
},
{
"path": "about",
"updated": "3987"
}
]
}
"
I tried to code part of for-loop
let json = JSON(jsonData)
for ( ) in json {
let filepath =
let updated =
// do searching another json to found file exists and updates
}
It's on the README, under the section named "loop": https://github.com/SwiftyJSON/SwiftyJSON#loop
// If json is .Dictionary
for (key,subJson):(String, JSON) in json {
//Do something you want
}
// If json is .Array
// The `index` is 0..<json.count's string value
for (index,subJson):(String, JSON) in json {
//Do something you want
}
Applied to your specific JSON structure:
let jsonData = """
{
"css": [
{
"path": "style.css",
"updated": "12432"
},
{
"path": "base.css",
"updated": "34627"
}
],
"html": [
{
"path": "home.htm",
"updated": "3223"
},
{
"path": "about",
"updated": "3987"
}
]
}
""".data(using: .utf8)!
let json = JSON(data: jsonData)
for (_, subJson):(String, JSON) in json {
for (_, subJson):(String, JSON) in subJson {
let filepath = subJson["path"].stringValue
let updated = subJson["updated"].stringValue
print(filepath + " ~ " + updated)
}
}
Using Swift 4 Codable:
struct FileInfo: Decodable {
let path, updated: String
}
let dec = try! JSONDecoder().decode([String:[FileInfo]].self,from: jsonData)
print(dec)
As per your JSON structure, use this :
for (index,subJson):(String, JSON) in json {
print(index) // this prints "css" , "html"
for (key,subJson):(String, JSON) in subJson {
let filepath = subJson["path"]
let updated = subJson["updated"]
}
}

Resources