I am trying to parse the JSON below (actual data is 20x the format listed)
{
message = "";
result = (
{
Ask = "4.8e-05";
BaseVolume = "32.61025363";
Bid = "4.695e-05";
Created = "2017-06-06T01:22:35.727";
High = "5.44e-05";
Last = "4.69e-05";
Low = "4.683e-05";
MarketName = "BTC-1ST";
OpenBuyOrders = 293;
OpenSellOrders = 4186;
PrevDay = "4.76e-05";
TimeStamp = "2018-02-20T00:00:31.863";
Volume = "662575.93818332";
},
This is the code that I have right now. It successfully prints the value "Last" to the console but when I incorporate the Dispatch.Queue, I get a Thread 1: signal SIGBRT not printing the value to the label.
let myJson = try JSONSerialization.jsonObject(with: content) as! [String:Any]
if let info = myJson["result"] as! [[String:Any]]?
{
for i in 0..<20 {
if i == 1
{
if let dict = info[i] as? [String:Any]
{
if let price = dict["Last"]
{
print(price)
//DispatchQueue.main.async
//{
// self.label1.text = price as String
//}
}
}
}
Any help is greatly appreciated!
Most likely your self.label1 outlet isn't connected. Fix that connection.
You should also update the if let that gets the value for the "Last" key as follows:
if let price = dict["Last"] as? String{
print(price)
DispatchQueue.main.async {
self.label1.text = price
}
}
There is some other cleanup you can do as well:
if let myJson = try JSONSerialization.jsonObject(with: content) as? [String:Any] {
if let info = myJson["result"] as? [[String:Any]] {
for (index, dict) in info.enumerated() {
if index == 1 {
if let price = dict["Last"] as? String {
print(price)
DispatchQueue.main.async {
self.label1.text = price
}
} // else no "Last" or not a String
}
}
} // else "result" doesn't contain expected array of dictionary
} // else content isn't a valid JSON dictionary
Avoid all of those forced casts. Especially avoid force casting to an optional.
JSON doesn't use the = sign or the semicolon. Change every = to a colon and every semicolon to a comma, so that
Ask = "4.8e-05";
BaseVolume = "32.61025363";
Bid = "4.695e-05";
Becomes
Ask: "4.8e-05",
BaseVolume: "32.61025363",
Bid: "4.695e-05",
Related
I understand that I can't add or remove an element from an array while it's being enumerated, but...I'm not! I think I have narrowed down where the crash happens but it doesn't make any sense to me.
func sendToCloud() {
for quoteNumber in newQuotes {
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Quotes")
let predicate = NSPredicate(format: "quoteNumber == %#", quoteNumber)
fetchRequest.predicate = predicate
fetchRequest.fetchLimit = 1
do {
//The next two lines is where the crash happens...
quotes = try context.fetch(fetchRequest)
let currentQuote = quotes.first as! Quotes
//-------------------------------------------
prepRecordForCoreData(obj: currentQuote, recordName: currentQuote.ckrecordname!, recordType: "Quotes")
repRecordForCoreData(obj: currentQuote.customer!, recordName: currentQuote.ckrefcustomer!, recordType: "Customers")
} catch let error as NSError {
print("ERROR SAVING TO CLOUD", error)
}
}
//clear array
newQuotes = []
coreData.saveContext { (success) -> Void in
if success {
AppData.uploadRecords()
}
}
}
Just in case...
func prepRecordForCoreData(obj: SignatureManagedObject, recordName: String, recordType: String) {
let zone = CKRecordZone(zoneName: Contstants.Strings.zoneName)
let id = CKRecord.ID(recordName: recordName, zoneID: zone.zoneID)
let record = CKRecord(recordType: recordType, recordID: id)
let coder = NSKeyedArchiver(requiringSecureCoding: true)
record.encodeSystemFields(with: coder)
let metadata = coder.encodedData
obj.ckmetadata = metadata
obj.ckrecordname = recordName
obj.ckupload = true
}
I wrote an API which returns the username and amount and at what time the transaction was placed. I got the response from the backend as an array of objects and I stored it as NSArray in client side. And I want to attach that response to labels so I converted that NSArray into String and In Database some fields are empty so the response returns the null values whenever the response returns the null values I am getting this error like "Could not cast the value of NSNUll to NSString". What I thought is replace the null value in that array with string. I tried so much but it always shows the same error how to resolve that problem. This is my code :
let response = JSON as! NSDictionary
//example if there is an id
let deyaPaybalance = response.object(forKey: "Details")
print(deyaPaybalance!)
let Amount1:[Double] = (response.object(forKey: "Amount")) as! [Double]
print("Amount is",Amount1)
for ele:Double in Amount1 {
self.amo += [String(ele)]
}
print("amount is in string",self.amo)
let time = response.object(forKey: "Time") as! NSArray
print("time is", time)
let id = response.object(forKey: "TransactionID")
print("id is",id!)
let name:NSArray = response.object(forKey: "RName") as!NSArray
print("name is",name)
// let len = name.count
for (object) in name.enumerated() {
if let i = name.index(of: "null") {
print("hey it's nnull")
//name.index(of: "null")
}
else {
print("hello")
}
}
print("name",name)
// It is used to get the date from the time tsamp
for element in time {
let ele = element
let formatter = ISO8601DateFormatter()
//print("date is",date1!)
formatter.formatOptions = [.withFullDate,
.withTime,
.withDashSeparatorInDate,
.withColonSeparatorInTime]
self.date2 = formatter.date(from: ele as! String)!
self.anotherFormatter.dateFormat = "MMM dd yyyy, h:mm a" // It is used to to show the date in th form of month year and time
self.anotherFormatter.string(from: self.date2)
let b = self.anotherFormatter.string(from: self.date2)
let final = b.replacingOccurrences(of: ",", with: " ")
let trimmedString = final.trimmingCharacters(in: .whitespaces)
self.dt += [trimmedString] // it is stored the final date and time
print("final tim is",trimmedString)
}
// End of the for loop
print(self.dt)
let contactViewController = self.storyboard?.instantiateViewController(withIdentifier: "TransactionDetails")as! TransactionDetails
contactViewController.method = deyaPaybalance as! [String]
contactViewController.amount = self.amo
contactViewController.timestamp = self.dt
contactViewController.transactionid = id as! [String]
contactViewController.name = name as! [String]// I am getting error here.
self.navigationController?.pushViewController(contactViewController, animated: true)
self.dismiss(animated: false, completion: nil)
UIApplication.shared.endIgnoringInteractionEvents()
You need to use like this to handle null in swift.
if let arr_name = name as? [String]{
contactViewController.name = arr_name
}else{
contactViewController.name = []
}
For replacing nil value in [String]
var name = ["a",nil,"3"]
if let nil_index = name.index(of: nil){
name[nil_index] = "empty"
}
print(name as! [String]) // Output is ["a", "empty", "3"]
I'm running a for loop to get values returned from JSON. I'm getting the latitude values more specifically. I'm rounding the values using dblLat = (dblLat * 100).rounded() / 100
When appending the values to a new Array, only the first element is appended correctly as rounded, thereafter each new element is appended as a double with 15 decimal places:
do {
let json = try JSONSerialization.jsonObject(with: data, options: [])
//print(json)
var latArray = [Double]()
guard let array = json as? [Any] else { return }
for user in array {
guard let userDict = user as? [String: Any] else { return }
guard let userID = userDict["id"] as? Int else { print("No Int Value Present"); return }
guard let name = userDict["name"] as? String else { return }
print(name)
guard let company = userDict["company"] as? [String : String] else { return }
print(company)
guard let companyName = company["name"] as? String else { return }
print(companyName)
guard let address = userDict["address"] as? [String : Any] else { return }
guard let geo = address["geo"] as? [String : String] else { return }
print(geo)
guard let lat = geo["lat"] as? String else { return }
guard var dblLat = Double(lat) else { return }
dblLat = (dblLat * 100).rounded() / 100
print(dblLat)
latArray.append(dblLat)
print(latArray)
//print(lat)
print(userID)
}
} catch {
print(error)
}
Printing the array:
[-37.32, -43.950000000000003, -68.609999999999999, 29.460000000000001, -31.809999999999999, -71.420000000000002, 24.890000000000001, -14.4, 24.649999999999999, -38.240000000000002]
The Binary representation of some numbers is just infinite. Have a look here.
You could use a NumberFormatter to get strings with two decimal places
let array = [-37.32, -68.609999999999999, 29.460000000000001, -31.809999999999999, -71.420000000000002, 24.890000000000001, -14.4, 24.649999999999999, -38.240000000000002]
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.minimumFractionDigits = 2
formatter.maximumFractionDigits = 2
let roundedStringsArray = array.map {formatter.string(from: NSNumber(floatLiteral: $0))!}
print(roundedStringsArray)
I don't understand how to get array from dictionary, i have tried in this code but i want get array only content and type
This is my array
{
wsResponse = {
aarti =(
{
content = "";
identifier = "slok_one";
title = 1;
type = "\U092d\U0915\U094d\U0924\U093e\U092e\U0930";
},
{
content = "";
identifier = "slok_two";
title = 2;
type = "\U092d\U0915\U094d\U0924\U093e\U092e\U0930";
},
{
content = "";
identifier = "slok_three";
title = 3;
type = "\U092d\U0915\U094d\U0924\U093e\U092e\U0930";
}
}
);
};
Here is my code
Alamofire.request(url, method: .get, parameters: nil, encoding: JSONEncoding.default)
.responseJSON { response in
if let status = response.response?.statusCode {
switch(status){
case 201:
print("example success")
default:
print("error with response status: \(status)")
}
}
//to get JSON return value
if let array = response.result.value
{
let JSON = array as! NSDictionary
print("\(JSON)")
let response = JSON["wsResponse"] as! NSDictionary
let data = response["aarti"]
}
}
i want array from this ,like content,title,type
thank you in advance
According to the JSON this prints all values in the aarti array:
if let JSON = response.result.value as? [String:Any] {
if let response = JSON["wsResponse"] as? [String:Any],
let aarti = response["aarti"] as? [[String:Any]] {
for item in aarti {
let content = item["content"] as! String
let identifier = item["identifier"] as! String
let title = item["title"] as! Int
let type = item["type"] as! String
print(content, identifier, title, type)
}
}
}
Basically do not use NSDictionary / NSArray in Swift.
If you want to put all content values in an array use flatMap. The line can replace the whole repeat loop.
let contentArray = aarti.flatMap { $0["content"] as? String }
PS: If you are going to create multiple arrays from the values don't do that: Use a custom struct or class
if someone want to get dictionary of array and use it in tableview
declaration:
var list:[Any] = []
and initialisation :
self.list = (self.ListDic?["data"] as! NSArray!) as! [Any]
and use:
let dictObj = self.list[indexPath.row] as! NSDictionary
print("object value: ",dictObj["text"] as! String)
I am parsing JSON and appending the data to an array, and while the array contains the correct number of elements, it is just the same element over and over, whatever the last one added was. Here is the code I am using:
if (statusCode == 200) {
do{
let json = try NSJSONSerialization.JSONObjectWithData(data!, options:.AllowFragments)
if let ns = json as? NSArray{
for ns in ns{
if let name = ns["name"] as? String{
if let number = ns["number"] as? Int{
if let cn = ns["cyclenumber"] as? Int{
if let url = ns["url"] as? String{
self.c.name = name
self.c.number = number
self.c.cycleNumber = cn
self.c.url = url
self.n.array.append(self.c)
}
}
}
}
}
}
}catch {
print("Error with Json: \(error)")
}
}
When I print the array, it just prints however many elements were added, but they are all duplicates of the last element added.
The problem is that you keep appending the sane instance - namely, self.c. Since the type of c is a class, not struct, no copying is going on; the same reference is added to the array over and over again.
You can fix this problem by making c's type a struct, or by assigning a new c on each iteration of the loop:
if let url = ns["url"] as? String {
var c = TypeOfC() // Make a new instance
c.name = name
c.number = number
c.cycleNumber = cn
c.url = url
self.n.array.append(c)
}
Note that c is no longer a member of self. Since you are changing c inside a loop, making it a member was very likely a mistake in the first place.
Answer's already been given, but I thought I should clean up your code a bit :)
guard let data = data where statusCode == 200 else {
return
}
do{
let json = try NSJSONSerialization.JSONObjectWithData(data, options:.AllowFragments)
if let ns = json as? NSArray{
for ns in ns{
if let name = ns["name"] as? String, number = ns["number"] as? Int,
cn = ns["cyclenumber"] as? Int, url = ns["url"] as? String{
self.c.name = name
self.c.number = number
self.c.cycleNumber = cn
self.c.url = url
self.n.array.append(self.c)
}
}
}
}catch {
print("Error with Json: \(error)")
}