I want to populate an array I have with JSON data. I'm using SwiftyJSON and Alamofire. I'm new to parsing JSON, so i apologize for any ignorance on my end. The URL below is the url i'm inserting in getAllTimeAverage(). Any help would be awesome!! thanks!
This is the JSON Data
https://apiv2.bitcoinaverage.com/indices/global/history/BTCILS?period=alltime&format=json
This is the array i want to populate
var allTimeAverages: [Any] = []
These are my functions. I call them in my cellForRowAt:, when i print the allTimeAverages.count, I get back zero.
func getAllTimeAverage(url: String) {
Alamofire.request(url, method: .get)
.responseJSON { response in
if response.result.isSuccess {
print("Sucess! Got the Bitcoin Data")
let bitcointJSON : JSON = [JSON(response.result.value!)]
self.updateAverageAllTime(json: bitcointJSON)
} else {
print("Error: \(String(describing: response.result.error))")
self.price = "Connection Issues"
}
}
}
func updateAverageAllTime(json: JSON) {
if let allTimeAverage = json["average"].dictionaryObject {
self.allTimeAverages.append(allTimeAverage)
}
}
func getBitcoinData(url: String) {
Alamofire.request(url, method: .get)
.responseJSON { response in
if response.result.isSuccess {
print("Sucess! Got the Bitcoin Data")
let bitcointJSON : JSON = JSON(response.result.value!)
self.updateBitcoinData(json: bitcointJSON)
} else {
print("Error: \(String(describing: response.result.error))")
self.price = "Connection Issues"
}
}
}
Here is an example of how this is to be done (I have taken a few values from the JSON API you have shared):
let jsonString = "[{\"high\": 23043.41,\"open\": 21494.60,\"low\": 21338.34,\"average\": 21668.01,\"time\": \"2018-06-29 00:00:00\",\"volume\": 102148.30132998565},{\"high\": 22488.75,\"open\": 22405.51,\"low\": 21380.97,\"average\": 22241.29,\"time\": \"2018-06-28 00:00:00\",\"volume\": 69383.44795111718},{\"high\": 22491.85,\"open\": 22169.36,\"low\": 21940.47,\"average\": 22224.29,\"time\": \"2018-06-27 00:00:00\",\"volume\": 69884.07809550199},{\"high\": 22707.46,\"open\": 22635.32,\"low\": 22004.29,\"average\": 22480.86,\"time\": \"2018-06-26 00:00:00\",\"volume\": 71611.8914173987}]";
if let jsonData = jsonString.data(using: .utf8, allowLossyConversion: false) {
let json = JSON(data: jsonData)
let jsonArray = json.arrayValue
let averagesArray = jsonArray.map{ $0["average"].doubleValue}
let highArray = jsonArray.map{ $0["high"].doubleValue}
let lowArray = jsonArray.map{ $0["low"].doubleValue}
let volumeArray = jsonArray.map{ $0["volume"].doubleValue}
let openArray = jsonArray.map{ $0["open"].doubleValue}
}
Making your solution work according to the above:
In the following line, remove [] as you are already getting an array from the API.
let bitcoinJSON : JSON = [JSON(response.result.value!)]
so the above line will become
let bitcoinJSON : JSON = JSON(response.result.value!)
Now, you can get the array value like I have done:
let jsonArray = bitcoinJSON.arrayValue
and now you can utilize the rest of the code (repeated below):
let averagesArray = jsonArray.map{ $0["average"].doubleValue}
let highArray = jsonArray.map{ $0["high"].doubleValue}
let lowArray = jsonArray.map{ $0["low"].doubleValue}
let volumeArray = jsonArray.map{ $0["volume"].doubleValue}
let openArray = jsonArray.map{ $0["open"].doubleValue}
Related
func llamadaApiDos(postData: (Data),empresa: String,boundary: String) -> [String] {
var request = URLRequest(url: URL(string: "https://www.something.com")!,timeoutInterval: Double.infinity)
request.addValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
request.httpBody = postData
var success = false
var serviceResponse = [""]
let semaphore = DispatchSemaphore(value: 0)
let task = URLSession.shared.dataTask(with: request, completionHandler: { data, response, error in
if let error = error {
print("Error while trying to re-authenticate the user: \(error)")
} else if let response = response as? HTTPURLResponse,
300..<600 ~= response.statusCode {
print("Error while trying to re-authenticate the user, statusCode: \(response.statusCode)")
} else if let data = data {
let loginDataModel = try! JSONDecoder().decode(responseLogin.self,from: data)
serviceResponse = JSONDecoder.decode(loginDataModel)
success = true
}else{
success = true
}
semaphore.signal()
})
task.resume()
_ = semaphore.wait(timeout: DispatchTime.distantFuture)
if success
{
return serviceResponse
}else
{
return ["Error"]
}
}
Cannot assign value of type '(T.Type, Data) throws -> T' to type '[String]'
I need to convert the JSON response into an array that can be validated in another function, but I don't know what type of data I should return, I'm sorry if it's not well understood, my English isn't very good either.
To convert the JSON response to an array in Swift, you can use the JSONSerialization class to convert the response data to a dictionary, then access the array stored in the dictionary using the key for the array.
Here's an example:
let json = try JSONSerialization.jsonObject(with: data, options: [])
if let array = json["keyForArray"] as? [String] {
// Use the array here
}
In your code, you can use this approach to convert the JSON response to an array, then return the array from the llamadaApiDos function.
Here's how your function would look like with this change:
func llamadaApiDos(postData: (Data),empresa: String,boundary: String) -> [String] {
var request = URLRequest(url: URL(string: "https://www.something.com")!,timeoutInterval: Double.infinity)
request.addValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
request.httpBody = postData
var success = false
var serviceResponse = [""]
let semaphore = DispatchSemaphore(value: 0)
let task = URLSession.shared.dataTask(with: request, completionHandler: { data, response, error in
if let error = error {
print("Error while trying to re-authenticate the user: \(error)")
} else if let response = response as? HTTPURLResponse,
300..<600 ~= response.statusCode {
print("Error while trying to re-authenticate the user, statusCode: \(response.statusCode)")
} else if let data = data {
// Convert the JSON response to an array
let json = try JSONSerialization.jsonObject(with: data, options: [])
if let array = json["keyForArray"] as? [String] {
// Use the array here
serviceResponse = array
success = true
}
}else{
success = true
}
semaphore.signal()
})
task.resume()
_ = semaphore.wait(timeout: DispatchTime.distantFuture)
if success
{
return serviceResponse
}else
{
return ["Error"]
}
}
I have an app where a user reviews an array of users. Example:
["user1","user2","user3","user4"]
When the user reviews the first user the app should present the second user for voting. Unfortunately when a user votes on the user2, user3, user4; the value for user1 is what's put in the database. I tested the PHP via postman and there's no issue there, so it has to be in the swift code. Here is my code:
func loadCards()->[String] {
let username = user!["username"] as! String
let url = URL(string: "http://localhost/shotsCenter.php")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
let body = "username=\(username)"
request.httpBody = body.data(using: .utf8)
// launch session
URLSession.shared.dataTask(with: request) { data, response, error in
// getting main queue of proceeding inf to communicate back, in another way it will do it in background
// and user will no see changes :)
DispatchQueue.main.async(execute: {
if error == nil {
do {
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? [String: AnyObject]
// clean up
self.valueArray.removeAll(keepingCapacity: false)
self.circleArray.removeAll(keepingCapacity: false)
// delcare new secure var to store json
guard let parseJSON = json else {
print("Error while parsing")
return
}
// declare new secure var to store $returnArray["users"]
guard let parseUSERS = parseJSON["users"] else {
print(parseJSON["message"])
return
}
self.valueArray = parseUSERS as! [AnyObject]
if self.valueArray.count > 0 {
let num_currentLoadedCardsArrayCap = (self.valueArray.count > MAX_BUFFER_SIZE) ? MAX_BUFFER_SIZE : self.valueArray.count
for (i, value) in self.valueArray.enumerated() {
let ava = self.valueArray[i]["ava"]
let id = self.valueArray[i]["id"]
let age = (NSString(format: "%#", self.valueArray[i]["age"] as! CVarArg))
let city = self.valueArray[i]["city"]
let state = self.valueArray[i]["state"]
self.age.append(age as AnyObject)
self.city.append(city as AnyObject)
self.state.append(state as AnyObject)
let url = NSURL(string: ava! as! String)!
let imageData = try? Data(contentsOf: url as URL)
let image = UIImage(data: imageData!)!
self.circleArray.append(image)
let reviewed = self.valueArray[i]["username"]
self.reviewed.append((reviewed as AnyObject) as! String)
print("reviewed user", reviewed! as Any)
let newCard = self.createDraggableViewWithData(at: i, value:value as! NSDictionary)
self.allCardsArray.append(newCard)
if i < num_currentLoadedCardsArrayCap {
self.currentLoadedCardsArray.append(newCard)
}
}
for (i,_) in self.currentLoadedCardsArray.enumerated() {
if i > 0 {
self.viewTinderBackGround.insertSubview(self.currentLoadedCardsArray[i], belowSubview: self.currentLoadedCardsArray[i - 1])
}
else {
self.viewTinderBackGround.addSubview(self.currentLoadedCardsArray[i])
}
self.currentIndex += 1
}
self.animateCardAfterSwiping()
self.perform(#selector(self.createDummyCard), with: nil, afterDelay: 1.0)
}
} catch {
// get main queue to communicate back to user
DispatchQueue.main.async(execute: {
let message = "\(error)"
})
return
}
} else {
DispatchQueue.main.async(execute: {
let message = error!.localizedDescription
})
return
}
})
} .resume()
return reviewed
}
func insertShot(_ rating: String, _ reviewed2: NSDictionary) {
let reviewer = user!["username"] as! String
let reviewed2 = reviewed[index]
let url = URL(string: "http://localhost/shotsCenter.php")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
// param to be passed to php file
let param = [
"user" : reviewer,
"revieweduser" : reviewed2,
"rating" : rating
] as [String : Any]
// body
let boundary = "Boundary-\(UUID().uuidString)"
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
// ... body
request.httpBody = createBodyWithParams(param as? [String : String], boundary: boundary)
// launch session
URLSession.shared.dataTask(with: request) { data, response, error in
// get main queu to communicate back to user
DispatchQueue.main.async(execute: {
if error == nil {
do {
// json containes $returnArray from php
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
// declare new var to store json inf
guard let parseJSON = json else {
print("Error while parsing")
return
}
// get message from $returnArray["message"]
let message = parseJSON["message"]
//print(message)
// if there is some message - post is made
if message != nil {
// reset UI
// self.msgTxt.text = ""
// switch to another scene
//self.tabBarController?.selectedIndex = 3
//_ = self.navigationController?.popViewController(animated: true)
}
} catch {
// get main queue to communicate back to user
DispatchQueue.main.async(execute: {
let message = "\(error)"
appDelegate.infoView(message: message, color: colorSmoothRed)
})
return
}
} else {
// get main queue to communicate back to user
DispatchQueue.main.async(execute: {
let message = error!.localizedDescription
appDelegate.infoView(message: message, color: colorSmoothRed)
})
return
}
})
}.resume()
}
No idea what currentIndex is for. Sth about the view hierarchy?
index is an interesting candidate. The only times it is used is in
let reviewed2 = reviewed[index]
and I see no modification to it. Since usernames are stored in there with
let reviewed = self.valueArray[i]["username"]
I think you are sending the same username for all four ratings, since reviewed2 is then made of the .httpBody. That's a guess from what I can see.
Tip: Codable
Codable may save you a lot of the ugliness of juggling around with AnyObject & co, since you'll have a [User] array instead of.. 4 separate arrays which you access with [index]. https://app.quicktype.io will get you started quickly by providing you with the parsing code for the given JSON.
I am sending a request to my vapor 1.5 server via Alamofire with body of type [String:Any] where Any type is a dictionary of String:String
When the request is received on the server I convert it to JSON type
guard let reqJson = request.json else {return}
How can I loop through this JSON object and convert it to an array of [String:Any]
The body of the request I send from the client app looks like this:
["DHSKL3920JFLSKXFgs":
["title": “some title”,
"body": “some body”,
"DHSKL3920JFLSKXFgs": "DHSKL3920JFLSKXFgs",
"unreadMessagesCount": 3],
"PKF993AVG59gkCM":
["title": “some title”,
"body": “some body”,
"DHSKL39": "DHSKL39",
"unreadMessagesCount": 3]]
You can use swift4 Codable and shrink your code to 4-5 lines. Documentation
If I understood you correctly. Maybe the following will help.
//This method uses high order function map
func convert(json:[String:Any]) -> [[String: Any]] {
let requiredObjects = json.map { $0.value as! [String:Any] } //force unwrapping
return requiredObjects
}
//This method uses simple loop
func convert(json:[String:Any]) -> [[String: Any]] {
var requiredObjects = [[String:Any]]()
for (key, value) in json.enumerated() {
requiredObjects.append([value.key : value.value])
}
return requiredObjects
}
struct DataFromClientSendNotifications {
let title: String
let body: String
let sound: String
let badge: String
let fcmToken: String
let unreadMessagesCount: String
}
guard let reqJson = request.json else {
throw Abort.custom(status: .badRequest, message: message)
}
for obj in reqJson.object! {
print("new obj is \(obj)")
let objKey = obj.key
let objValue = obj.value.object
print("objectValue here is \(objValue)")
let title = objValue?["title"]?.string
let body = objValue?["body"]?.string
let unreadMessagesCount = objValue?["unreadMessagesCount"]?.string
let sound = objValue?["sound"]?.string
let badge = objValue?["badge"]?.string
let fcmToken = objValue?["objValue"]?.string
let itemCompleted = DataFromClientSendNotifications(title: title!, body: body!, sound: sound!, badge: badge!, fcmToken: fcmToken!, unreadMessagesCount: unreadMessagesCount!)
print("itemCompleted is \(itemCompleted)")
//now you can do whatever you want with itemCompleted
}
Can Anyone Help me with this
my data after parsing a JSON URL is
{
AREA = (
{
"area_name" = "Bhaktamadhu Nagar";
"city_id" = 4;
id = 31;
price = "100.00";
},
{
"area_name" = "Gandamunda";
"city_id" = 4;
id = 32;
price = "100.00";
}
);
}
and there is a lot more.
I want to fetch only area_name and price values in an array
my code is something like that
do {
let parsedData = try JSONSerialization.jsonObject(with: data!, options: .mutableLeaves) as! NSDictionary
print(parsedData)}
I am getting my Upper format in the parsedData
What is the exact code for getting my area_name and price which should store in two separate arrays as aname[] and price[]
Please don't mark it as a duplicate already searched a lot before posting this.
Your JSON data is converted into [String: AnyObject].
AREA data is [[String: AnyObject]] so create a [String: AnyObject] array. and getting a one by one value from array.
How to fetch JSON data from a url using URLSession?
try this code. it's helpfull
URLSession.shared.dataTask(with: url) { (data, response, error) in
if let jsonData = data {
do {
let parsedData = try JSONSerialization.jsonObject(with: jsonData, options: .mutableLeaves) as! [String: AnyObject]
if let area = parsedData["AREA"] as? [[String: AnyObject]] {
for a in area {
areaNameArr.append(a["area_name"])
priceArr.append(a["price"])
print(a)
}
}
}
catch let error {
debugPrint(error)
}
}
else {
debugPrint(error as Any)
}
}.resume()
Use the SwiftyJSON Lib.
It’s easy and fast.
I am using it and it’s very helpful in this way:
let session = URLSession(configuration: URLSessionConfiguration.ephemeral)
self.Task = session.dataTask(with: RequestLink as URLRequest , completionHandler: { (data,response,error) in
if error != nil {
print(error as Any)
}
let ReadJson4Rest = JSON(data: data!)
if let Rest_Details = ReadJson4Rest["Result"].array{
for Details in Rest_Details {
let Comment = Details.dictionaryValue["Comment"]!
let UserName = Details.dictionaryValue["User_ID"]!
if Comment != nil {
let FirstChar = UserName.description.characters.first
self.GetUserImage(UserName: UserName.string! ,AlphabetCat: (FirstChar?.description)!)
DispatchQueue.main.async {
self.CommentValue.append(Comment.string!)
self.UserNames.append(UserName.string!)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "Load"), object: nil)
}
}
}
}
})
self.Task?.resume()
}
I need to send many variables to server. Previously I was using construction like this:
let myURL = NSURL(string: "http://example.com");
let request = NSMutableURLRequest(URL:myURL!);
request.HTTPMethod = "POST";
let postString = "param1=\(var1)¶m2=\(var2)"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding);
Now I need to send not only variables like param1 and param2 but few arrays. I know that there is library called Alamofire but it is not supporting iOS 7.
You can do something like this,
let mapDict = [ "a":"First", "b":"Second"]
let json = [ "title":"kk" , "dict": mapDict ]
let jsonData = NSJSONSerialization.dataWithJSONObject(json, options: .PrettyPrinted, error: nil)
// create post request
let url = NSURL(string: "http://example.com/post")!
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "POST"
// insert json data to the request
request.HTTPBody = jsonData
let task = NSURLSession.sharedSession().dataTaskWithRequest(request){ data,response,error in
if error != nil{
println(error.localizedDescription)
return
}
if let responseJSON = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: nil) as? [String:AnyObject]{
println(responseJSON)
}
}
task.resume()
You can use array instead of dictionary as per your requirement. hope this will help. :)