Parsing JSON for iOS app in Swift Issue - ios

First of all, this is a noob question so anyone interested can answer me , because I'm just a beginner.
So, I need to parse JSON data from an api that my college seniors created for our annual technical festival. But they forgot to put a name to the array which contains all info.
1
They forgot to put the name and the role is similar to the "loans" at the beginning 2
I am using SwiftyJSON to parse the data and here is my code.
func getJSON(){
let url = NSURL(string: baseURL)
let request = NSURLRequest(URL:url!)
let session = NSURLSession(configuration:NSURLSessionConfiguration.defaultSessionConfiguration())
let task = session.dataTaskWithRequest(request) { (data, response, error) -> Void in
if error == nil{
let swiftyJSON = JSON(data:data!)
let loan1 = swiftyJSON["loans"][0]["status"].stringValue
print(loan1)
}else{
print("There is an error")
}
}
task.resume()
}
So i would like to know that what could "loans" be replaced by to get my JSON parsing up and running. I have already tried " " and "" to be sure.
Thanks !

Based on the JSON dictionary you posted, you aren't accessing any existing keys so loan1 can't possibly be anything other than nil. Based on the response in the first image, you get back an array of dictionaries.
[
{
"eid": 98,
"ename": "Lights. Camera. Tweet",
"sname": "IEEE GTBIT",
"ebanner": "http://s10.postimg.org/a11cezdft/12045587_1594466984176579_4873790458939193947_o.jpg",
"time": "1459189800854",
"category": "Literary & Management",
"desc": "Lights. Camera. Tweet! brings you a chance to win ..."
},
{
"eid": 45,
"ename": "Hack#GTBIT",
"sname": "Android Techies",
"ebanner": "http://i.imgur.com/ANR84uk.jpg",
"time": "1459222200397",
"category": "Technical",
"desc": "Hack#GTBIT is a Software Hackathon where particip..."
},
etc...
If none of this data is what you're looking for, you're not requesting properly or the data being returned isn't being properly formatted or including all the necessary information.
It's possible you could make a new request to check the status using the ID or some other value; you would access that through swiftyJSON[0]["eid"] – that would get you the value 98. But the key–value pair you're trying to access isn't correct based on the response. The "loans" key doesn't exist at the top level and the "status" key also does not exist.

Related

iOS Swift How to get value of any key from json response

I am getting a response from an API
["response": {
record = {
title = "Order Add";
usercart = 5345;
};
}, "status": success, "message": تم إضافة السجل بنجاح]
I got the Value for status Key from the code
let statusCode = json["status"].string
Now i want the value for the key usercart in string value
I am using this code but getting any response.
let order_id = json["response"]["record"]["usercart"].string
Please help me to get this value.
As you are using SwiftyJSON and you are trying to get usercart value as a string but the usercart is Int.
So if you want this in string formate you should need to use .stringValue instead of .string else you can use .int or .intValue in form of int.
json["response"]["record"]["usercart"].stringValue
The json you are getting from server is wrong. Instead it should be -
["response": {
"record" : {
"title" : "Order Add",
"usercart" : 5345
};
}, "status": success, "message": تم إضافة السجل بنجاح]
There is nothing like = in json
Also if server response cannot change I would suggest reading this whole thing as string and then using search in string, though it is very bad approach.
if you are using SwiftyJSON then use this to get value
json["response"]["record"]["usercart"].stringValue

Can't retrieve the info after downloading this data

I'm trying to access the data downloaded from a website which looks like this:
{"quizzes":[
{"id":1, "question": "Can't solve this :("},
{"id":2, "question": "Someone help pls"}]}
The data downloaded looks way more complex, with more values, more keys, and some keys being associated to another dictionary of Key:String, but since I can't even access the most simple fields I thought I would start with this.
I'm using JSONSerialization, so my question is:
If I want to create a variable where i can save the downloaded data... Which would be it's type? I would say [String:[String:Any]], but I'm not sure if "quizzes" represents a key on this specific key, since the data starts with '{' and not with '['.
Instead of using JSONSerialization one could use JSONDecoder.
Example
struct Question: Decodable {
let id: Int
let question: String
}
struct Quiz: Decodable {
let quizzes: [Question]
}
Assuming jsonStr is a string with the JSON in your question:
if let jsonData = jsonStr.data(using: .utf8) {
if let quiz = try? JSONDecoder().decode(Quiz.self, from: jsonData) {
for question in quiz.quizzes {
print("\(question.id) \"\(question.question)\"")
}
}
}
Output
1 "Can't solve this :("
2 "Someone help pls"

Is there a way to search venues by price using the Foursquare API?

I'm creating an iOS project in Swift using the Foursquare API this API, and SwiftyJSON. Is there any way to get Venue results that match a certain price tier?
I understand how to receive venue results including the price tier, but, aside from checking the price tier and filtering out the relevant ones, I'm not sure how to receive venues only matching a certain price tier.
EDIT:
My current code looks like this:
func setUpFoursquare(){
let client = FoursquareAPIClient(clientId: "JMBLK0SDZ0N2NF5TG3UCLMOF4FA5FKA14AIOZ4P4TS4MHEWO", clientSecret: "*****")
let parameter: [String: String] = [
"near": "Toronto",//destination!,
"limit": "4",
"query": "sushi",
"price": "1",
];
print("Parameter: \(parameter)");
print("client: \(client)");
//The path is based on the request link. For example, the request link for photos is:
//GET https://api.foursquare.com/v2/venues/VENUE_ID/photos
//So the path would correspond tovenues/VENUE_ID/photos where VENUE_ID is the corresponding ID.
client.request(path: "venues/search", parameter: parameter) { result in
// client.request(path: "venues/categories", parameter: parameter) { result in
switch result {
case let .success(data):
print("Success")
guard let json = try? JSON(data: data) else{
print("\(#function): Unable to retrieve json object")
return
}
print("Json: \(json)")
if json["meta"]["code"] == 200{
self.parse(jsonObject: json)
}
case let .failure(error):
// Error handling
switch error {
case let .connectionError(connectionError):
print(connectionError)
case let .responseParseError(responseParseError):
print(responseParseError) // e.g. JSON text did not start with array or object and option to allow fragments not set.
case let .apiError(apiError):
print(apiError.errorType) // e.g. endpoint_error
print(apiError.errorDetail) // e.g. The requested path does not exist.
}
}//end switch
}//end client.request
}
However the "price":"1" parameter doesn't actually alter the results.
Using the venues/explore endpoint you can filter results by price tiers. See the documentation here: https://developer.foursquare.com/docs/api/venues/explore
Specifically, you will need to use the price parameter:
Comma separated list of price points. Currently the valid range of
price points are [1,2,3,4], 1 being the least expensive, 4 being the
most expensive. For food venues, in the United States, 1 is < $10 an
entree, 2 is $10-$20 an entree, 3 is $20-$30 an entree, 4 is > $30 an
entree.
Using the API wrapper you linked to, that would look something like this...
let parameter: [String: String] = [
"ll": "35.702069,139.7753269",
"limit": "10",
"price": "1,2"
];
client.request(path: "venues/explore", parameter: parameter) { result in
// do your SwiftyJSON stuff
}

How to access data in array in JSON

JSON:
{
"projects":[
{
"id":113,
"name":"Mobile app Android",
"description":"",
"created_on":"2014-10-03T16:53:56+02:00",
"updated_on":"2014-12-03T16:59:45+01:00"
},
{
"id":142,
"name":"Mobile app iOS",
"created_on":"2014-12-11T18:30:55+01:00",
"updated_on":"2014-12-11T18:30:55+01:00"
},
{
"id":52,
"name":"Test project",
"identifier":"grafikr",
"description":"",
"created_on":"2013-10-14T17:21:33+02:00",
"updated_on":"2014-10-10T17:40:47+02:00"
},
{
"id":37,
"name":"Sample project",
"identifier":"grafikf",
"description":"",
"created_on":"2013-09-18T16:31:25+02:00",
"updated_on":"2013-09-26T13:11:58+02:00"
}
],
"total_count":4,
"offset":0,
"limit":25
}
It is easy to access for example name of the first project (with name Mobile app Android) by var name = json["projects"][0]["name"].stringValue
But how do I access all names in SwiftyJSON? If I make a variable var projects = json["projects"], it gives me:
[
{
"id" : 113,
"created_on" : "2014-10-03T16:53:56+02:00",
"name" : "Mobile app Android",
"description" : "",
"updated_on" : "2014-12-03T16:59:45+01:00"
},
...
Now I don't have a problem with making a NSDictionary from data anymore, but this drives me crazy.
There's a lot going on in your code sample—perhaps too much to be addressed by a single Stack Overflow question / answer.
I would strongly recommend going back to Apple's resources for Swift and iOS application patterns. Topics to revisit would include synchronous versus asynchronous programming, authentication, and using data sources with table views.
This should probably work. Your json also contains "total_count", which looking at it, I assume that's the count of the number of projects. Pull that count out, loop over till the count and fetch the name.
var names = [String]()
let count = json["total_count"].int
for index in 0..<count {
let name = json["projects"][index]["name"].string
names.append(name)
}
Why not use SwiftyJSON the Swifty way???
Try this:
let names = json["projects"].arrayValue.map {
$0["name"].stringValue
}

JSON text did not start with array or object and option to allow fragments not set

I'm sending this json response from server for a request to my IOS 7 app.
{
"root": {
"success": "1",
"message": "Successfully retrieved data.",
"data": {
"records": [
{
"receipt_key": "xxxxxxxx",
"receipt_id": "xxxxxxxx",
"store_name": "xxxxxx",
"amount": "xxxx",
"date_purchase": "xxxxxxxx",
"is_processed": "x",
"created_on": "xxxxxxxx",
"modified_on": "xxxxxxxx",
"modified_on_millis": "xxxxxxxx",
"user_folder": "xxxxxxxx",
"category_id": "xxxxxxxx",
"is_deleted": "x",
"currency_id": "xxxxxxxx"
}
]
}
}
}
I use the following code for parsing the above json to NSDictionary object.
NSMutableDictionary *json=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
But I'm getting this error on the above code.
Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be
completed. (Cocoa error 3840.)" (JSON text did not start with array or
object and option to allow fragments not set.) UserInfo=0x8a8a700
{NSDebugDescription=JSON text did not start with array or object and
option to allow fragments not set.}
I ran into the same error when consuming a feed from a php page. Just as you encountered, the resulting json string passed a visual inspection, but would fail to serialize. My suspicion was that there was a hidden character somewhere the feed, so I converted each character to its unicode decimal equivalent and examined the results:
NSString *feedStr = [[NSString alloc] initWithData:feedData encoding:NSUTF8StringEncoding];
for(int i=0; i<[feedStr length]; ++i)
{
unichar c = [feedStr characterAtIndex:i];
NSLog(#"decimal char %d", c);
}
I found that before the first character and after the last was the character #65279. After a quick google search I found What is this char? 65279, where this was identified as a byte order mark.
In my case, I was able to fix this at the source by opening and saving all included php files, using a text editor that provided an option to use the "Encode in UTF-8 without BOM" encoding. For more info on the php side, see How to avoid echoing character 65279 in php?
It usually is because of some warning message throwing out from your server without putting it in the response array. For example in PHP, some "warning messages" are not caught in your array so that when you finally use "echo json_encode($RESPONSE_ARR)," it is not a JSON format.
The JSON that you posted looks Ok. If that is what your iOS application received, it would get parsed. Even if it wasn't Ok, you wouldn't get this error message. JSON must start with '[' if it is an array, and '{' if it is a dictionary like yours, and everything else you get the error message that you got. So even if you sent '[934knsdf239][###' you wouldn't get this error message, because the data starts with the [ indicating an array.
You need to debug this in the iOS application. First convert the data to a string and print that and check it. If the string looks alright then print the data itself - sometimes people manage to add 0 bytes or control characters, or two byte order markers or something similar which are invisible in the string but are not legal JSON.
The option NSJSONReadingAllowFragments allows JSON that consists just of a string, number, boolean or null value. Don't use this unless you want to be able to process one of these on its own.
I faced the same problem. But I found that the Url I was sending as a param to server was wrong. There was a little one character mistake. For example I was sending the below url
URL = https://somerUrl/api/v2/&venues/search?client_id=jkdasljf3242jka-fsdf-fadsfasd&lat=40.712488&long=-74.006277&distance=25
The mistake was extra & symbol in front of venues making trouble. So i removed & symbol and found worked for me. So, make sure you are sending the correct param to server.
The problem comes from response parsing. You are trying to de-serialize a JSON response (which MUST be contained in either an NSArray or NSDictionary) however your response is none of the above (Most likely a simple string).
You can try to Print out your server response. Please use the code in your catch block like. and identifying an error in server side or not.
Your server data is not proper JSON format then print out your server data and check a server data is valid or not.
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]
}
catch let err{
print("\n\n===========Error===========")
print("Error Code: \(error!._code)")
print("Error Messsage: \(error!.localizedDescription)")
if let data = data, let str = String(data: data, encoding: String.Encoding.utf8){
print("Server Error: " + str)
}
debugPrint(error)
print("===========================\n\n")
debugPrint(err)
}
}
else {
debugPrint(error as Any)
}
}.resume()

Resources