Wrong value in correct json using Swift - ios

I'm facing this strange problem. I have to parse this json and extract "symbol","High","low" and "direction". this is the original json
[{"ID":101,"Symbol":"PKR","Bid":105.7,"Ask":106,"High":105.7,"Low":106,"Change":0,"Direction":"0","CreateDate":"04:38:26","EntityState":2,
"EntityKey":{"EntitySetName":"v_openmarketrates","EntityContainerName":"tradebizEntities",
"EntityKeyValues":[{"Key":"ID","Value":101}],
"IsTemporary":false}},
{"ID":1,"Symbol":"EUR","Bid":126.696,"Ask":127.327,"High":126.7622,"Low":126.9752,"Change":0.4192,"Direction":"0","CreateDate":"06:37:31","EntityState":2,
"EntityKey":{"EntitySetName":"v_openmarketrates","EntityContainerName":"tradebizEntities","EntityKeyValues":[{"Key":"ID","Value":1}],
"IsTemporary":false}}]
When i'm parsing this in json, it is fetching all the values correctly except the value of "Direction",like this:
[{
Ask = 106;
Bid = "105.7";
Change = 0;
CreateDate = "04:38:26";
Direction = 0;
EntityKey = {
EntityContainerName = tradebizEntities;
EntityKeyValues = (
{
Key = ID;
Value = 101;
}
);
EntitySetName = "v_openmarketrates";
IsTemporary = 0;
};
EntityState = 2;
High = "105.7";
ID = 101;
Low = 106;
Symbol = PKR;
},
{
Ask = "127.265";
Bid = "126.623";
Change = "0.3463";
CreateDate = "06:30:46";
Direction = 0;
EntityKey = {
EntityContainerName = tradebizEntities;
EntityKeyValues = (
{
Key = ID;
Value = 1;
}
);
EntitySetName = "v_openmarketrates";
IsTemporary = 0;
};
EntityState = 2;
High = "126.7306";
ID = 1;
Low = "126.9752";
Symbol = EUR;
}
i have no idea how the value inside json is getting changed while parsing even though rest of the values are correct. this is how i'm parsing it.
if let jsonResult = try JSONSerialization.jsonObject(with: data!, options: []) as? [NSDictionary] {
print("kerb rates full json = ",jsonResult )
for field in jsonResult as? [AnyObject] ?? [] {
print("fields of kerb rates = \(field)")
print("kerb directions \((field["Direction"] as? String)!)")
let subfield : AnyObject = (field["EntityKey"] as? AnyObject)!
let sub_subfield : AnyObject = (subfield["EntityKeyValues"] as? AnyObject)!
print("sub_subfield = \(sub_subfield)")
print("subfields = \(subfield)")
// for key_Subfield in sub_subfield as? [AnyObject] ?? [] {
print("inside loop!")
// converting int and bool values
let ask = (field["Ask"] as? Int)!
let bid = (field["Bid"] as? Int)!
let change = (field["Change"] as? Int)!
let EntityState = (field["EntityState"] as? Int)!
let High = (field["High"] as? Double)!
let ID = (field["ID"] as? Int)!
let IsTemporary = ""//(subfield["IsTemporary"] as? Bool)!
let Low = (field["Low"] as? Double)!
let Value = ""//(key_Subfield["Value"] as? Int)!
// it is crashing here due to multple dictionaries
self.Save_KerbRates(ask: (String(ask)),
bid: (String(bid)),
change: (String(change)),
createDate: (field["CreateDate"] as? String)!,
direction: (field["Direction"] as? String)!,
entityContainerName: "",//(subfield["EntityContainerName"] as? String)!,
entitiySetName:"",// (subfield["EntitySetName"] as? String)!,
entitiyState: (String(EntityState)),
high: (String(High)),
id: (String(ID)),
isTemporary: (String(IsTemporary)),
key:"",// (key_Subfield["Key"] as? String)!,
low: (String(Low)),
symbol: (field["Symbol"] as? String)!,
value: (String(Value)))
// }
}
Update:
After using [[String:Any]]
i'm still getting the wrong value of direction,like this
kerb rates full json = [["Low": 106, "Direction": 0, "EntityState": 2, "EntityKey": {
EntityContainerName = tradebizEntities;
EntityKeyValues = (
{
Key = ID;
Value = 101;
}
);
EntitySetName = "v_openmarketrates";
IsTemporary = 0;
}, "ID": 101, "CreateDate": 04:38:26, "Symbol": PKR, "Change": 0, "Ask": 106, "High": 105.7, "Bid": 105.7], ["Low": 126.9752, "Direction": -1, "EntityState": 2, "EntityKey": {
EntityContainerName = tradebizEntities;
EntityKeyValues = (
{
Key = ID;
Value = 1;
}
);
EntitySetName = "v_openmarketrates";
IsTemporary = 0;
}, "ID": 1, "CreateDate": 07:03:46, "Symbol": EUR, "Change": 0.4403, "Ask": 127.349, "High": 126.7654, "Bid": 126.717],

This parses (and prints) all values in the first level of the dictionary and the value for keys IsTemporary and Value in the second level. All variable names start with a lowercase letter to conform to the naming convention.
The code uses a type alias for convenience.
Be aware that the code does not use any error handling to check the dictionary keys. If it is not guaranteed that all items contain all keys and values you have to use optional bindings.
typealias JSONDictionary = [String:Any]
do {
if let jsonResult = try JSONSerialization.jsonObject(with:data!) as? [JSONDictionary] {
for field in jsonResult {
let ask = field["Ask"] as! Double
let bid = field["Bid"] as! Double
let change = field["Change"] as! Double
let createDate = field["CreateDate"] as! String
let direction = field["Direction"] as! String
let entityState = field["EntityState"] as! Int
let high = field["High"] as! Double
let id = field["ID"] as! Int
let low = field["Low"] as! Double
let symbol = field["Symbol"] as! String
let entityKey = field["EntityKey"] as! JSONDictionary
let isTemporary = entityKey["IsTemporary"] as! Bool
let entityKeyValues = entityKey["EntityKeyValues"] as! [JSONDictionary]
let value = entityKeyValues[0]["Value"] as! Int
print(ask, bid, change, createDate, direction, entityState, high, id, low, symbol, isTemporary, value)
}
}
} catch {
print(error)
}

Related

Efficient way to Insert and Update a core data object [2020]

Currently I am checking whether the object already exists in core data based on id and then updating and inserting. Is there any better way to do it? Have added "id" as a unique constraint, Which prevents inserting of objects with same "id". Does inserting just update the existing object with same id?
#nonobjc public class func saveUserMovies(movieJSON: [[String: Any]], user: UserProfile, isFavorites: Bool = false, isWatchlisted: Bool = false) {
let context = MMPersistentStore.sharedInstance.privateManagedObjectContext
for movie in movieJSON {
let movieID = movie["id"] as! Int
let fetchMovieWithIDRequest = fetchMovieRequest()
let moviePredicate = NSPredicate(format: "id == %d", movieID)
let sortDiscriptor = NSSortDescriptor(key: "id", ascending: false)
fetchMovieWithIDRequest.sortDescriptors = [sortDiscriptor]
fetchMovieWithIDRequest.predicate = moviePredicate
var userMovie: UserMovie?
context.performAndWait {
do {
userMovie = try fetchMovieWithIDRequest.execute().first
} catch {
print(MMErrorStrings.coreDataFetchError)
}
}
if let fetchedMovie = userMovie {
fetchedMovie.genreIds = movie["genre_ids"] as? [Int64]
fetchedMovie.adult = movie["adult"] as? Bool ?? false
if isFavorites {
fetchedMovie.isFavorite = isFavorites
} else {
fetchedMovie.isWatchlisted = isWatchlisted
}
fetchedMovie.video = movie["video"] as? Bool ?? false
fetchedMovie.backdropPath = movie["backdrop_path"] as? String
fetchedMovie.originalLanguage = movie["original_language"] as? String
fetchedMovie.originalTitle = movie["original_title"] as? String
fetchedMovie.overview = movie["overview"] as? String
fetchedMovie.posterPath = movie["poster_path"] as? String
fetchedMovie.releaseDate = movie["release_date"] as? String
fetchedMovie.releaseYear = String(fetchedMovie.releaseDate?.prefix(4) ?? "")
fetchedMovie.title = movie["title"] as? String
fetchedMovie.popularity = movie["popularity"] as? Double ?? 0.0
fetchedMovie.voteCount = movie["voteCount"] as? Int64 ?? 0
fetchedMovie.voteAverage = movie["voteAverage"] as? Double ?? 0.0
MMPersistentStore.sharedInstance.save(context: context)
} else {
let fetchedMovie = UserMovie(context: context)
fetchedMovie.id = movie["id"] as? Int64 ?? 0
fetchedMovie.user = user
fetchedMovie.genreIds = movie["genre_ids"] as? [Int64]
fetchedMovie.adult = movie["adult"] as? Bool ?? false
if isFavorites {
fetchedMovie.isFavorite = isFavorites
} else {
fetchedMovie.isWatchlisted = isWatchlisted
}
fetchedMovie.video = movie["video"] as? Bool ?? false
fetchedMovie.backdropPath = movie["backdrop_path"] as? String
fetchedMovie.originalLanguage = movie["original_language"] as? String
fetchedMovie.originalTitle = movie["original_title"] as? String
fetchedMovie.overview = movie["overview"] as? String
fetchedMovie.posterPath = movie["poster_path"] as? String
fetchedMovie.releaseDate = movie["release_date"] as? String
fetchedMovie.releaseYear = String(fetchedMovie.releaseDate?.prefix(4) ?? "")
fetchedMovie.title = movie["title"] as? String
fetchedMovie.popularity = movie["popularity"] as? Double ?? 0.0
fetchedMovie.voteCount = movie["voteCount"] as? Int64 ?? 0
fetchedMovie.voteAverage = movie["voteAverage"] as? Double ?? 0.0
MMPersistentStore.sharedInstance.save(context: context)
}
}
}
}
Have added "id" as a unique constraint, Which prevents inserting of objects with same "id".
I didn't use it before yet
Does inserting just update the existing object with same id?
No, it'll insert the new object.
For your case, you could make a refactoring, please refer the findOrCreate function in https://github.com/objcio/core-data/blob/master/SharedCode/Managed.swift
It'll help you avoid duplicated code.
One more thing, your request doesn't need the sortDescriptor, and it should have the limit = 1, and returnObjectAsFaults = false for optimisation.
After that, you just need to make sure your function is called in the same context to avoid duplications.

Could not cast value of type '__NSSingleObjectArrayI' to 'NSDictionary' in Swift

When I parse the Api I got response and stored full response to Dictionary then I split it to array and dictionary, But I get error so please help to solve the error,
Here I give the code what I am tried.
let responseDictionary:NSDictionary = responseObject as! NSDictionary
print(responseDictionary)
if let statusCode:NSNumber = responseDictionary.value(forKey: "success") as? NSNumber{
if statusCode == 1{
print("statusCode :",statusCode)
let incomingRequetArray:NSArray = responseDictionary.value(forKey: "incoming_requests") as! NSArray
print("incomingRequetArray",incomingRequetArray)
if (incomingRequetArray.count > 0)
{
let requestDataDict:NSDictionary = incomingRequetArray.value(forKey: "request_data") as! NSDictionary -----> Error in this line
print("requestDataDict",requestDataDict)
let ownerArray:NSArray = requestDataDict.value(forKey: "owner") as! NSArray
print("ownerArray",ownerArray)
self.mutDictOwner = ownerArray.object(at: 0) as! NSMutableDictionary
}
}
responseDictionary is
"incoming_requests" = (
{
datetime = "2017-04-17 12:25:58";
later = 0;
"request_data" = {
dog = (
);
owner = {
address = "";
"d_latitude" = "0.00000000";
"d_longitude" = "0.00000000";
"dest_latitude" = "0.00000000";
"dest_longitude" = "0.00000000";
latitude = "11.01449160";
longitude = "76.98273220";
name = "Sss Sas";
"num_rating" = 0;
"payment_type" = 1;
phone = "+919123456789";
picture = "";
rating = "0.00";
};
"payment_mode" = 1;
};
"request_id" = 1474;
"request_services" = 30;
"time_left_to_respond" = 21;
}
);
"is_approved" = 1;
"is_approved_txt" = Approved;
"is_available" = 1;
success = 1;
It is because your "request_data" is an Object and not a Dictionary, see how "incoming_request" has started (with a " ( ") and "request_data" is starting with "{". what you can do to access is this
let requestDataDict:NSDictionary = incomingRequetArray.value(forKey: "request_data") as! [AnyObject]-----> Error in this line
print("requestDataDict",requestDataDict)
let x = requestDataDict[0] as! NSDictionary
let ownerArray:NSArray = x.value(forKey: "owner")as! NSArray
your are doing wrong incomingRequetArray is NSArray and you are getting value for key
Write this
let requestDataDict:NSDictionary = incomingRequetArray[0]as!NSDictionary
let newDict: NSDictionary = requestDataDict.object(forKey: "request_data")
print("newDict is ---%#", newDict)
you have used NSDictionary and NSArray format So I have written the code according to yours. But for further uses in swift Do not use NSDictionary and NSArray.
This is a reasonable Swift transcription which solves the error. It uses a type alias for convenience.
typealias JSONDictionary = [String:Any]
let responseDictionary = responseObject as! JSONDictionary
print(responseDictionary)
if let success = responseDictionary["success"] as? Int, success == 1 {
print("statusCode :", success)
let incomingRequestArray = responseDictionary["incoming_requests" as! [JSONDictionary]
print("incomingRequetArray",incomingRequestArray)
if let requestDataDict = incomingRequestArray.first {
print("requestDataDict",requestDataDict)
if let ownerArray = requestDataDict["owner"] as? [JSONDictionary], !ownerArray.isEmpty {
print("ownerArray",ownerArray)
self.mutDictOwner = ownerArray[0] as! JSONDictionary
}
}
In the line that's throwing an error try to change incomingRequetArray.value... to incomingRequetArray[0].value... as you need to access the internal dictionary that's contained in an array and then query for the value for given key.

Why can I not access the second level of this array in Swift?

I have the following array which is passed from an API call from a PHP Script:
["playerForm": {
1 = (
{
date = "2017-01-31";
name = Dicky;
result = L;
"results_id" = 42;
},
{
date = "2016-12-24";
name = Dicky;
result = W;
"results_id" = 19;
}
);
2 = (
{
date = "2017-01-25";
name = G;
result = W;
"results_id" = 38;
},
{
date = "2017-01-25";
name = G;
result = D;
"results_id" = 40;
},
{
date = "2017-01-21";
name = G;
result = L;
"results_id" = 34;
}
);
3 = (
{
date = "2017-01-31";
name = Sultan;
result = W;
"results_id" = 42;
},
{
date = "2017-01-15";
name = Sultan;
result = L;
"results_id" = 30;
}
);
}]
However I cannot seem to access the 1,2,3 parts of it...
let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String:AnyObject]
print (json!)
if let dict = json?["playerForm"] as? [String:AnyObject] {
print ("step 1")
if let arr = dict["1"] as? [[String:String]] {
print ("step 2")
self.leagueForm = arr.flatMap { Form($0) }
print (self.leagueForm)
print (self.leagueForm.count)
for i in 0..<self.leagueForm.count {
let form = self.leagueForm[i]
print (form.player_results!)
self.formGuide.append(form.player_results!)
}
print ("now")
print (self.formGuide)
self.resultsDisplay.results = self.formGuide
self.resultsDisplay.results = self.resultsDisplay.results.reversed()
self.resultsDisplay.displayResults()
}
}
With this code above it only gets as far as Step 1.
What am I doing wrong?
UPDATED WITH PROGRSS*
let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String:AnyObject]
print (json!)
if let dict = json?["playerForm"] as? [String:AnyObject] {
print ("step 1")
for (_ , value) in dict {
if let arr = value as? [[String:Any]] {
print(arr)
//your code
}
}
}
Custom Struct to define array:
struct Form {
var player_result: String?
var player_name: String?
var result_date: String?
var result_id: String?
init(_ dictionary: [String : Any]) {
self.player_result = dictionary["result"] as? String ?? ""
self.player_name = dictionary["name"] as? String ?? ""
result_date = dictionary["date"] as? String ?? ""
result_id = String(dictionary["results_id"] as? Int ?? 0)
}
}
Change your array type [[String:String]] to [[String:Any]] because it contains both String and Number as value.
if let arr = dict["1"] as? [[String:Any]] {
print(arr)
//your code
}
Note: You need to loop through the dict Dictionary because its each key having array.
for (_ , value) in dict {
if let arr = value as? [[String:Any]] {
print(arr)
//your code
}
}

Get the index out of AnyObject list of items IOS

parsed is an NsDictionary and I am pulling the balances out of it via
if let findbalances: AnyObject = parsed["balances"]
which gives me a list of balances in AnyObject format
(
{
"available_amount" = 133519;
currency = AUD;
},
{
"available_amount" = 7854;
currency = CAD;
},
{
"available_amount" = 88581;
currency = EUR;
},
{
"available_amount" = 0;
currency = GBP;
},
{
"available_amount" = 63618;
currency = INR;
},
{
"available_amount" = 375;
currency = NZD;
},
{
"available_amount" = 0;
currency = TRY;
},
{
"available_amount" = 2918958;
currency = USD;
}
)
I know that
let whatCurrency = (findbalances[7]["currency"] as! String)
=USD But how do I find that value [7] if the amount of objects changes?
I want to match on USD
I tried
let defaultcurr = "USD"
let findUSD = findbalances.indexOfObject(defaultcurr)
but that gave me 9223372036854775807
How do I just find 7
9223372036854775807 is NSNotFound.
You can use a closure as argument of indexOf
let defaultcurr = "USD"
let findUSDIndex = findbalances.indexOf { ($0["currency"] as! String) == defaultcurr }
Or you can filter the entire row
let findUSD = findbalances.filter { ($0["currency"] as! String) == defaultcurr }.first
indexOfObject seems to be using NSArray. Don't do that. Use Swift native Array and cast your collection object to [[String:AnyObject]] :
if let findbalances = parsed["balances"] as? [[String:AnyObject]] { ...

NIL when Parsing JSON

I am trying to parse and get the values from this structure of JSON:
["mst_customer": 1, "data": {
0 = 2;
1 = 1;
2 = 1;
3 = "JAYSON TAMAYO";
4 = "581-113-113";
5 = 56;
6 = on;
7 = g;
8 = jayson;
9 = active;
"app_access" = on;
id = 2;
"mst_customer" = 1;
name = "Jayson Tamayo";
status = active;
territory = 1;
}, "status": OK, "staff_id": 2, "staff_name": Jayson Tamayo]
I use the following Swift code to get the values:
(data: Dictionary<String, AnyObject>, error: String?) -> Void in
if error != nil {
print(error)
} else {
if let feed = data["data"] as? NSDictionary ,let entries = data["data"] as? NSArray{
for elem: AnyObject in entries{
if let staff_name = elem["name"] as? String{
print(staff_name)
}
}
}
}
I am trying to get the name by using the keys name or staff_name. But I always get nil.
you want to access staff_name, which is not in "data" variable ... you can simply get that like
if error != nil {
print(error)
} else {
if let name = data["staff_name"] as? String{
print(name)
}
}
for elem: AnyObject in entries{
if let songName = elem["name"] as? String{
print(songName)
}
}
//replace above code with below code
if let songName : String = entries["name"] as? String{
print(songName)
}

Resources