Extracting JSON Data - - arrays

I have the following JSON data structure being pulled from FBSDKGraphRequest.
data = (
{
id = "<USER_ID_GOES_HERE>";
name = "Tom Jones";
picture = {
data = {
"is_silhouette" = 0;
url = "<USER_IMAGE_URL_GOES_HERE>";
};
};
},
{
id = "<USER_ID_GOES_HERE>";
name = "Tom Jones";
picture = {
data = {
"is_silhouette" = 0;
url = "<USER_IMAGE_URL_GOES_HERE>";
};
};
},
{
id = "<USER_ID_GOES_HERE>";
name = "Tom Jones";
picture = {
data = {
"is_silhouette" = 0;
url = "<USER_IMAGE_URL_GOES_HERE>";
};
};
},
I want to extract the data and place it into an array. I am having difficulty with the first "data" key.
Heres my FBSDKGR:
let params = ["fields": "name, picture.type(large)"]
let request = FBSDKGraphRequest(graphPath: "me/taggable_friends", parameters: params)
request!.start { (connection, result, error) -> Void in
if error != nil {
print("There is some error getting friends", error!)
}
else if result != nil {
print("Here is the result", result!)

With an extra dependency, if you don't mind.
import SwiftyJSON
let json = JSON(result) // after you get result from FBSDKGR
let data = json["data"].array
for (index, _) in data.enumerated() {
if let id = json["data", index, "id"].int {
// add to your array
if let name = json["data", index, "name"].string {
// continue nesting...
}
}
}

As your JSOND dta is array of dictionary so , we can cast the result by the following way . First of all we will take two array , one is for names list and other is for picture details . here picture details array is array of dictionary . let's go for code
var namesArray = [String]()
var ImageDetailsArrayDict= [[String :AnyObject]]()
let params = ["fields": "name, picture.type(large)"]
let request = FBSDKGraphRequest(graphPath: "me/taggable_friends", parameters: params)
request!.start { (connection, result, error) -> Void in
if error != nil {
print("There is some error getting friends", error!)
}
else if result != nil {
print("Here is the result", result!)
if let response = result["data"] as? [[String :AnyObject]] {
for i in 0..<response.count {
namesArray.append(response[i]["name"] as! String)
ImageDetailsArrayDict.append(response[i]["picture"])
}
}
}
}
Now , we have two array . so we can easily populate it in the tableView .
Good luck .

Related

How to get value from json in iOS Swift?

I have JSON with dynamic data of all key values. Right now I am trying to get value by finding "type = object" if an object exists then in values I will check the contentType exists in values.
How to find the value matched inside JSON and convert it into an array?
Here is my code:
switch response.result {
case .success:
guard let data = response.value else {
return
}
if let JSON = response.value {
let json = JSON as? [String: AnyObject]
print("json view docue",json)
if let castedDict = json as? [String: String] {
print("Converted successfully: \(castedDict)")
} else {
print("Failed to cast the dictionary")
}
let vc = self.stringify(json: json)
print("new json converted into string:::", vc.count)
}
self.view.removeLoading()
case .failure(let error):
print("Error:", error)
self.view.removeLoading()
}
Here is my JSON:
{
image1: {
type = Object;
value = "{\"contentType\":\"image/jpeg\",\"url\":\"https://www.pexels.com/photo/neon-advertisement-on-library-glass-wall-9832438/",\"fileName\":\"9832438.jpg\"}";
valueInfo = {
objectTypeName = "com.google.gson.JsonObject";
serializationDataFormat = "application/json";
};
},
image2: {
type = Object;
value = "{\"contentType\":\"image/jpeg\",\"url\":\"https://www.pexels.com/photo/neon-advertisement-on-library-glass-wall-9832438/",\"fileName\":\"9832438.jpg\"}";
valueInfo = {
objectTypeName = "com.google.gson.JsonObject";
serializationDataFormat = "application/json";
};
}
}
Any much appreciated pls...

How can I remove whole dictionary in nested array at specific index after filter some specific value

I have API response with nested array . But I can't understand how can I remove whole Dict by filtering the value .
This is the response screenshot
https://imgur.com/XIDyfYX
here is the json Resonse :- https://del.dog/lofavofogo.json
I have tried this but I don't know how to get filter nested value and remove whole dict at specific index
How to remove pairs from dictionary at specific index - Swift?
I want to remove the dict where section name are "NA"
Here is the code :-
Model Class For API Response :-
class filterclass: NSObject {
var classesID : String?
var classname : String?
var section = [filterSections]()
init(json: [String: Any]) {
if let classname = json["class"] as? String {
self.classname = classname
}
if let classesID = json["classesID"] as? String {
self.classesID = classesID
}
print("classname",classname)
if let evUserGoing = json["classsection"] as? [[String: Any]] {
if self.section.count > 0
{
self.section.removeAll()
}
for evUser in evUserGoing {
// print("evUser",evUser)
let userGoing = filterSections(json: evUser)
self.section.append(userGoing)
}
for sec in section {
let section = sec.secctionname
let setionID = sec.sectionID
}
}
}
}
class filterSections: NSObject {
var sectionID : String?
var secctionname : String?
var isSelctedSection : Bool = false
init(json: [String: Any]) {
if let sectionID = json["sectionID"] as? String {
self.sectionID = sectionID
}
if let secctionname = json["section"] as? String {
self.secctionname = secctionname
}
print("sectioname",secctionname)
}
}
API POST Method TO hit API :-
func getClassSectionAPI() {
if ReusableClass.sharedInstance.isNetworkAvailable() == true
{
ReusableClass.sharedInstance.showActivityIndicator()
let UUid = LoginUserInfo.sharedInstance.uuid!
let dictionary = ["uuid":UUid,"device_id":devicetoken,"school_id":LoginUserInfo.sharedInstance.schoolId!, "user_type":LoginUserInfo.sharedInstance.usertype!]
print(dictionary)
let encoder = JSONEncoder()
if let jsonData = try? encoder.encode(dictionary) {
if let jsonString = String(data: jsonData, encoding: .utf8) {
// print(jsonString)
let cipher:String = CryptoHelper.encrypt(input:jsonString)!;
let NewEncryption = "data=\(cipher)"
print(NewEncryption)
let hmac_md5 = cipher.hmac(algorithm: .sha512, key: kHMACKey)
print("hmac",hmac_md5)
UserDefaults.standard.set(hmac_md5, forKey: Headerkey)
Singleton.sharedInstance.getWebservicesverify(params: NewEncryption, Methodname: KFilterClassSection, data: Stringnil)
{ (result) in
DispatchQueue.main.async {
ReusableClass.sharedInstance.hideActivityIndicator()
}
if result != nil
{
do {
let jsonData = try JSONSerialization.data(withJSONObject: result)
if let json = String(data: jsonData, encoding: .utf8) {
let Dict = function.convertToDictionary(text: json)! as NSDictionary
guard let data = Dict[KData] as? String
else
{
return
}
self.baseDict = data
}
}
catch {
}
guard let output = CryptoHelper.decrypt(input:self.baseDict)
else
{
return
}
print(output)
let mainDict = function.convertToDictionary(text: output)! as NSDictionary
let status = mainDict[KStatus] as! NSInteger
if(status == 1)
{
DispatchQueue.main.async {
print("Main dict",mainDict)
guard let messageArray = mainDict["data"] as? [[String: Any]] else{
return
}
if self.arrayClasSection.count > 0
{
self.arrayClasSection.removeAll()
}
print("Main dict",messageArray)
for arr in messageArray {
let obj = filterclass.init(json: arr)
if let index = self.arryFilterTemperary.index(where: { $0.classname == obj.classname }) {
// let filtered = self.arryFilterTemperary.filter { $0.classname == "NA" }
obj.section = self.arryFilterTemperary[index].section
self.arrayClasSection.append(obj)
for sec in self.arryFilterTemperary[index].section {
let section = sec.sectionID
let sectionName = sec.secctionname
self.NASection = sec.secctionname!
print(self.NASection)
self.selectedNASectionID = sec.sectionID!
// let test = self.arryFilterTemperary[index].section.filter { !$0.value.contains("") }
// print(test)
}
}
else
{
self.arrayClasSection.append(obj)
}
}
ReusableClass.sharedInstance.hideActivityIndicator()
self.tableFilter.reloadData()
}
}
I want to append the data to array but before appending I want to
filter that "NA" value dict from the array
Since this is your first question I go to some greater length in answering it than usual. Playgrounds are an exceptional way to demonstrate your problem, so you should always try to compose your questions in a form of one. I will post my answer directly from the Playground I have done.
With that out of the way lets get to the question. Your main problem seems to be that you tried an ill fated JSONSerialization "shortcutt" route. This looks cheap from the outside, but working with the unavoidable optionality of a [String:Any] comes at a high cost in a language like Swift. The way to go is the brilliant Codable protocol, at least in my opinion. Once you define your data structure properly Xcode has so much more possibilities to guide you through the APIs that writing your filter code becomes a piece of cake.
Enough of the ranting, let's get to the pizza.
import UIKit
let dataStr = """
{
"status":1,
"message":"Class and sections list",
"data":[
{
"classsection":[
{
"section":"A",
"sectionID":"1",
"classesID":"1"
},
{
"section":"B",
"sectionID":"3",
"classesID":"1"
}
],
"class":"First",
"classesID":"1"
},
{
"classsection":[
{
"section":"A",
"sectionID":"2",
"classesID":"2"
},
{
"section":"B",
"sectionID":"7",
"classesID":"2"
}
],
"class":"Second",
"classesID":"2"
},
{
"classsection":[
{
"section":"A",
"sectionID":"20",
"classesID":"15"
}
],
"class":"Third",
"classesID":"15"
},
{
"classsection":[
{
"section":"NA",
"sectionID":"33",
"classesID":"22"
}
],
"class":"Pre Nursery",
"classesID":"22"
},
{
"classsection":[
{
"section":"NA",
"sectionID":"34",
"classesID":"23"
},
{
"section":"A",
"sectionID":"35",
"classesID":"23"
},
{
"section":"B",
"sectionID":"36",
"classesID":"23"
},
{
"section":"C",
"sectionID":"37",
"classesID":"23"
}
],
"class":"Fourth four",
"classesID":"23"
},
{
"classsection":[
{
"section":"NA",
"sectionID":"38",
"classesID":"24"
}
],
"class":"Fifth",
"classesID":"24"
},
{
"classsection":[
{
"section":"NA",
"sectionID":"39",
"classesID":"25"
}
],
"class":"sixth 6th",
"classesID":"25"
}
]
}
"""
struct Section: Codable {
let section, sectionId, classesId: String
enum CodingKeys: String, CodingKey {
case sectionId = "sectionID"
case classesId = "classesID"
case section
}
}
struct Class1: Codable {
let classsection: [Section]
let clazz, classesId: String
private enum CodingKeys: String, CodingKey {
case classsection
case clazz = "class"
case classesId = "classesID"
}
}
struct Response: Codable {
let status: Int
let message: String
let data: [Class1]
func filterSections(notMatching filterVal: String) -> Response {
let filteredData = data.map { (clazz) -> Class1 in
let filteredSections = clazz.classsection.filter { (sect) -> Bool in
sect.section != filterVal
}
return Class1(classsection: filteredSections, clazz: clazz.clazz, classesId: clazz.classesId)
}
return Response(status: status, message: message, data: filteredData)
}
}
let jsonData = dataStr.data(using:.utf8)!
do {
let res = try JSONDecoder().decode(Response.self, from: jsonData)
let filteredResponse = res.filterSections(notMatching: "NA")
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
print(String(data:try encoder.encode(filteredResponse), encoding: .utf8)!)
} catch {
print(error)
}
As you can see your data structure is easily defined and the filtering code is really easy to understand once you wrap your head around the lambdas (which you should). The playground will output nicely formatted JSON as an answer, this way it is easy to check that your code does the right thing without all the messy parts of asynchronous communication (which are still nicely done in Swift).
Here's my last tipp of the day: Always try to isolate your problem as much as possible if you post a question on StackOverflow. I think your question carried too much legacy, you should whittle it down for the next one. This will improve your chances for a quick answer.

Issue with storing data within an Array - Swift

I currently have my set-up as followed:
I am running a query in Firebase to extract all of the genres within an array of genres, like so:
var genresLabelIndex : [String] = ["Horror", "Fiction", "Romance"]
Then I am creating a blank arrays for each of the genres to be able to store the information of the genres within each of the areas like so:
var horrorData = [InformationForFeed]()
var fictionData = [InformationForFeed]()
var romanceData = [InformationForFeed]()
InformationForFeed looks like so:
class InformationForFeed {
fileprivate var _uploadKey:String!
fileprivate var _userKey:String!
fileprivate var _imageURL:String!
fileprivate var _socialMedia:[String]
var uploadKey:String!{
return _uploadKey
}
var userKey:String!{
return _userKey
}
var imageURL:String!{
return _imageURL
}
init(dictionary:Dictionary<String,AnyObject>, socials: [String]) {
_socialMedia = socials
if let uploadKey = dictionary["upload_key"] as? String {
self._uploadKey = uploadKey
}
if let userKey = dictionary["user_key"] as? String {
self._userKey = userKey
}
if let imageURL = dictionary["imageUrl"] as? String {
self._imageURL = imageURL
}
}
}
I am then creating an Array of the list of genres arrays like so:
1) First I am creating an empty array of arrays like this:
var genreArrayIndex : [[InformationForFeed]] = []
2) Then within my init() of the UIView I am setting what will be in the array like this:
genreArrayIndex = [self.horrorData, self.fictionData, self.romanceData]
I then will run a function called getData() that will run my query and start storing the information.
I store my information of each genre in a tempArray, and then I set the genreArrayIndex[index] to equal the tempArray and then clear the tempArray as seen in getData below.
func getData() {
for genre in genresLabelIndex {
let dbReference = Database.database().reference().child("genres").child(genre)
let query = dbReference.queryLimited(toLast: 6)
query.observeSingleEvent(of: .value, with: { (snapshot : DataSnapshot) in
if snapshot.childrenCount > 0 {
for s in snapshot.children.allObjects as! [DataSnapshot] {
let item = s.value as! Dictionary<String,AnyObject?>
let facebook = (s.childSnapshot(forPath: "social_links").value as? NSDictionary)?["facebook_link"]
let audible = (s.childSnapshot(forPath: "social_links").value as? NSDictionary)?["audible_link"]
let amazon = (s.childSnapshot(forPath: "social_links").value as? NSDictionary)?["amazon_link"]
var socialsArray = [String]()
if facebook != nil {
socialsArray.append(facebook! as! String)
} else {
socialsArray.append("nil")
}
if audible != nil {
socialsArray.append(audible! as! String)
} else {
socialsArray.append("nil")
}
if amazon != nil {
socialsArray.append(amazon! as! String)
} else {
socialsArray.append("nil")
}
let data = InformationForFeed(dictionary: item as Dictionary<String,AnyObject>, socials: socialsArray)
self.newArray.append(data)
}
}
self.genreArrayIndex[self.genreArrayIndexCount] = self.newArray
self.genreArrayIndexCount = self.genreArrayIndexCount + 1
self.newArray.removeAll()
self.internalIndex = self.internalIndex + 1
if self.internalIndex == self.genresLabelIndex.count {
self.tableView.reloadData()
}
})
}
}
My tempArray looks like this:
var newArray = [InformationForFeed]()
The index looks like this:
var genreArrayIndexCount : Int = 0
Now comes the issue....
All of the information is properly being stored in the genreArrayIndex .....but... it is not actually storing the information in the arrays that being stored in genreArrayIndex.
So in other words if you were to print(self.genreArrayIndex) it would be fully populated. But if you were to print(self.fictionData) it would be blank.
How can I resolve this?
Array is a value type. That means its contents are copies. Initializing genreArrayIndex with empty horrorData, (and others) and then filling it with getData() does not also copy the data back into horrorData. I would recommend eliminating
genreArrayIndex = [self.horrorData, self.fictionData, self.romanceData]
and replacing horrorData, fictionData, ... with computed properties. Perhaps like this.
var horrorData: [InformationFeed] {
return genreArrayIndex[0]
}

Random photos in 12 views – Fatal error: Index out of range

I've got Thread 1: Fatal error: Index out of range looping my 7 photos from array in NSViews.
How to fix it?
let url = URL(fileURLWithPath: NSHomeDirectory()).appendingPathComponent("Desktop/ArrayOfElements")
do {
let fileURLs = try FileManager.default.contentsOfDirectory(at: url, includingPropertiesForKeys: nil, options: [.skipsHiddenFiles]).reversed()
let photos = fileURLs.filter { $0.pathExtension == "jpg" }
for index in photos {
let image = [NSImage(data: try Data(contentsOf: index))]
for view in arrayOfViews {
let i = Int(arc4random_uniform(UInt32(photos.count-1)))
view.image = image[i]
}
}
} catch {
print(error)
}
It seems that this line is wrong:
view.image = image[i]
image array has length = 1
Use view.image = image[0] instead
EDIT
let url = URL(fileURLWithPath: NSHomeDirectory()).appendingPathComponent("Desktop/ArrayOfElements")
do {
let fileURLs = try FileManager.default.contentsOfDirectory(at: url, includingPropertiesForKeys: nil, options: [.skipsHiddenFiles]).reversed()
let photos = fileURLs.filter { $0.pathExtension == "jpg" }
for view in arrayOfViews {
let i = Int(arc4random_uniform(UInt32(photos.count-1)))
let image = NSImage(data: try Data(contentsOf: photos[i]))
view.image = image
}
} catch {
print(error)
}
Try to create a category to Collection
extension Collection where Index == Int {
/**
Gives a random element of the collection.
- returns: A random element of the collection.
*/
func randomElement() -> Iterator.Element? {
return isEmpty ? nil : self[Int(arc4random_uniform(UInt32(endIndex)))]
}
}
Usage
let numbers = [1,2,3,4,5,6,7,8,9,10]
let randomNumber = numbers.randomElement()
print(randomNumber!)
Edit:
I guess you are making mistake in the following code
for view in arrayOfViews {
let i = Int(arc4random_uniform(UInt32(photos.count-1)))
view.image = image[i]
}
Let's assume photos objects having 10 elements and image object have less than 10 elements, so in such case, you will get this type of error. So change it to the following
for view in arrayOfViews {
let i = Int(arc4random_uniform(UInt32(image.endIndex)))
view.image = image[i]
}

How to convert returned array to dictionary with Swift 3

I'm using FB API to get the list of user's page likes. But i'm stuck with converting array (the array is the return data from FB API) to dictionary.
My code:
let params = ["fields": "about,name,created_time,picture", "limit": "3"]
Facebook.getUserPagesLikes(params: params, handler: { (userData) in
guard let pagesArrays = userData["data"] as? Array<Any> else {return}
print("page array: \(pagesArrays)")
}) { (error) in
print("cannot get FB pages: \(String(describing: error))")
}
Return Data:
[{
about = "This is the OFFICIAL facebook page for the Linus Tech Tips and TechQuickie YouTube channels. Run by our entire team. (Note: PMs are not read, use Twitter)";
"created_time" = "2017-08-03T04:23:08+0000";
id = 343018322461286;
name = LinusTech;
picture = {
data = {
"is_silhouette" = 0;
url = "https://scontent.xx.fbcdn.net/v/t1.0-1/p50x50/17021592_1241602709269505_8744271496063654606_n.jpg?oh=6b34199b5753bc64def8474713c3ae6c&oe=59F1F116";
};
};
}, {
about = "Wilaime.contact#gmail.com\nInstagram : #wilaime\nTwitter : #WilAime\nSnapchat : wil.aime";
"created_time" = "2017-07-05T13:41:50+0000";
id = 666964646732880;
name = "Wil Aime";
picture = {
data = {
"is_silhouette" = 0;
url = "https://scontent.xx.fbcdn.net/v/t1.0-1/p50x50/1964962_757890660973611_6828038531185039189_n.jpg?oh=f877b27948e68ea63dd95905a4f5642a&oe=5A2C75FD";
};
};
}]
Please help me to convert this array to dictionary so that I can access the name,about etc value. Thanks in advance
You can get dictionary value like.
for dic in pagesArrays{
let dicOne = dic as! NSDictionary
print(dicOne[about]!)
print[dicOne[name]!]
}

Resources