I am new to Objective-C, and JSON so I am confused on how to do this. I have looked up tutorials, and made sure my JSON is valid.
I have a SQL server database that I am trying to access by parsing JSON. I have checked to make sure my JSON is valid. Whenever I attempt to parse the JSON is Objective-C, however, it always returns null.
Here is my JSON:
[
{
"ID": 1,
"Username": "Cray",
"Password": "fake",
"Active": 0,
"LastLogin": null
}
]
Here is my Objective-C code:
NSString *urlString = [NSString stringWithFormat:#"http://quacknasty.com/service.php"];
NSURL *url = [NSURL URLWithString:urlString];
NSData *data = [NSData dataWithContentsOfURL:url];
NSError *error;
NSMutableDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSLog(#"test%#", json);
json always returns null when I do the NSLog
Easy one: Open the URL in a browser. You will see that you don't have valid JSON:
Conneection established.
[{"ID":1,"Username":"Cray","Password":"fake","Active":0,"LastLogin":null}]
You have to remove the echo of Connection established.\n
EDIT I: You have to use NSArray as root object, because the JSON string starts with []
EDIT II: Additionally you should set the correct HTTP Header fields as follows:
header('Content-Type: application/json; charset=utf-8');
Request to thi URL. Response is :
Conneection established.
<br />[{"ID":1,"Username":"Cray","Password":"fake","Active":0,"LastLogin":null}]
It's not json format
Related
I am calling an API in which I am sending a URL link as a post parameter with it.
But while converting it into JSON data using
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:lParameters options:NSJSONWritingPrettyPrinted error:&error];
it adds extra '\' character into the link.
and when I log that data string, it logs like
data string : {
"id" : "1",
"photoLink" : "https:\/\/7.7.100.120:8443\/webresource\/carsevent\/gallery\/approved\/image-a31ea5e0-6284-402a-9e6a-b0cdba37bc1f.png"
}
Log :
Dictionary :
{
id = 1;
photoLink = "https://7.7.100.120:8443/webresource/carsevent/gallery/approved/image-a31ea5e0-6284-402a-9e6a-b0cdba37bc1f.png";
}
So API is returning error in this case.
How can I overcome from this?
Any help would be much appreciable.
Thanks
JSON must have certain characters escaped with a "\" character and even though "/" is not required to be escaped it is allowed to be escaped. Therefor the JSON with escaped "/" characters is valid and should be accepted by the API.
You can remove them if needed.
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
jsonString = [jsonString stringByReplacingOccurrencesOfString:#"\\/" withString:#"/"];
jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
File a bug report: http://bugreport.apple.com requesting an option to not escape "/".
See this SO answer.
See JSON for the characters that must be escaped.
I am trying to convert a JSON string into an object in Objective C using the code:
NSString *jsonString = (NSString *) responseObject;
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
id json = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil];
The value of jsonString is
"[{\"Date\": \"12-01-2015\", \"Time\": \"7:00 am\", \"Title\":
\"First Car Service\", \"Details\": \"This was the first car
service ever done\"}]"
But the value of json is always nil. How do I convert the jsonString into a NSArray ?
My (third) bet: your json string isn't correct. If it contains the leading and trailing quotes strip them. Replaced the \" with ".
better: make the server or other json source send correct json.
From the error, it may be that your string is not formatted correctly, probably due to the quotes.
You should also make sure that after you have formatted the string, then you check the array has objects.
NSLog(#"JSON Details: %#", json[0][#"Details"]);
I'll keep this brief. I'm using this code to parse JSON from a local file into an array of objects:
-(void)populateData
{
NSString* sourcePath = [[NSBundle mainBundle]pathForResource:#"ships" ofType:#"json"];
//get json string
NSString* JSONData = [[NSString alloc] initWithContentsOfFile:sourcePath encoding:NSUTF8StringEncoding error:nil];
NSData* data = [JSONData dataUsingEncoding:NSUTF8StringEncoding];
//put json in array
ships = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
NSLog(#"%#", ships);
}
(Note: only showed one for the sake of brevity, there's ~20 entries in each one)
This method works for JSON formatted like this:
[
{
"name": "Santa Maria",
"operator": "Kingdom of Spain",
"flag": "flag_spain"
}
]
It returns null for JSON formatted like this:
[
{
"name": "Santa Maria",
"operator": "Kingdom of Spain",
"flag": "flag_spain",
"launched": "November 19, 1890",
"fate": "Destroyed in Havana, Cuba in Feburary 1898."
"cost":"$4,677,788.75",
"image": "maine_img",
"image_attribution": "Image is in the public domain."
}]
I haven't the faintest idea of why the smaller one works while the larger one doesn't. Any help would be appreciated.
There is a comma missing after:
"fate": "Destroyed in Havana, Cuba in Feburary 1898."
It's due to a syntax error on this line:
"fate": "Destroyed in Havana, Cuba in Feburary 1898."
(missing comma at the end)
There are tools to spot this kind of errors. For instance, http://jsonlint.com. This one seems to have better error messages http://jsonformatter.curiousconcept.com/.
And excuse me, but converting from NSData to NSString and then back to NSData is just pointless. Just call dataWithContensOfFile: and be done with it.
Update
It appears resultField is the one that has no value. Will look into this, but I'd still appreciate any advice.
Original Post
I've been set the task of coming up with a basic iOS application that simply makes a search request and then displays the results for university work. I tried to use the Google Custom Search engine but could never get it to work on the iPhone so I've had to resort to the depreciated Google Web Search API (The lecturer is okay with this).
Now, I'm able to make the request, and it returns the JSON data as intended, which I now must parse, I think. Sadly I only have a week to do this, which is crazy as I've never worked with JSON before.
What I'd like is if someone could help me get off the ground with a pointer or two in how to get even just a basic parsing of the JSON data.
I've looked around on Stackoverflow and saw some things that might be helpful like the breakdown structure in the selected answer here.
The person put this together, which when shown in the code makes some sense to me:
A great structure explanation
dictionary (top-level)
sethostname (array of dictionaries)
dictionary (array element)
msgs (string)
status (number)
statusmsg (string)
warns (array)
??? (array element)
Sadly I can't even begin to do the same with the code generated in my app. It takes the form similar to this example code, courtesy of google - I'm no Paris Hilton fan!
Example code from Google.
{"responseData": {
"results": [
{
"GsearchResultClass": "GwebSearch",
"unescapedUrl": "http://en.wikipedia.org/wiki/Paris_Hilton",
"url": "http://en.wikipedia.org/wiki/Paris_Hilton",
"visibleUrl": "en.wikipedia.org",
"cacheUrl": "http://www.google.com/search?q\u003dcache:TwrPfhd22hYJ:en.wikipedia.org",
"title": "\u003cb\u003eParis Hilton\u003c/b\u003e - Wikipedia, the free encyclopedia",
"titleNoFormatting": "Paris Hilton - Wikipedia, the free encyclopedia",
"content": "\[1\] In 2006, she released her debut album..."
},
{
"GsearchResultClass": "GwebSearch",
"unescapedUrl": "http://www.imdb.com/name/nm0385296/",
"url": "http://www.imdb.com/name/nm0385296/",
"visibleUrl": "www.imdb.com",
"cacheUrl": "http://www.google.com/search?q\u003dcache:1i34KkqnsooJ:www.imdb.com",
"title": "\u003cb\u003eParis Hilton\u003c/b\u003e",
"titleNoFormatting": "Paris Hilton",
"content": "Self: Zoolander. Socialite \u003cb\u003eParis Hilton\u003c/b\u003e..."
},
...
],
"cursor": {
"pages": [
{ "start": "0", "label": 1 },
{ "start": "4", "label": 2 },
{ "start": "8", "label": 3 },
{ "start": "12","label": 4 }
],
"estimatedResultCount": "59600000",
"currentPageIndex": 0,
"moreResultsUrl": "http://www.google.com/search?oe\u003dutf8\u0026ie\u003dutf8..."
}
}
, "responseDetails": null, "responseStatus": 200}
This is the code so far, which as you'll learn quickly does not really do much else than return code similar to the code above.
**My code.**
// query holds the search term
query = [query stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
//append theQuery with search URL
NSString *tempString = [NSString stringWithFormat:#"%#/%#", #"https://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=", theQuery];
//Create NSURL out of tempString
NSURL *url = [NSURL URLWithString:tempString];
// Create a request object using the URL.
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// Prepare for the response back from the server
NSHTTPURLResponse *response = nil;
NSError *error = nil;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONWritingPrettyPrinted error:&error];
NSDictionary* resultField = [NSDictionary dictionaryWithDictionary:[dictionary objectForKey:#"results"]];
// Send a synchronous request to the server (i.e. sit and wait for the response)
// Check if an error occurred
if (error != nil) {
NSLog(#"%#", [error localizedDescription]);
// Do something to handle/advise user.
}
// Convert the response data to a string.
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSArray *results = [dictionary objectForKey:#"results"];
//set label's text value to responseString's value.
endLabel.text = responseString;
Now the main issue I've encountered is that the results array is null all the time. I could really do with a point in the right direction here. Thank you.
It looks like you're having trouble traversing the data structure parsed out of the JSON.
NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONWritingPrettyPrinted error:&error];
Assuming the data you passed in is good, this dictionary contains the top-level structure. It has three keys responseData, responseDetails, and responseStatus. (You could see this by NSLogging the dictionary.)
You're then querying that dictionary for the key results. It doesn't exist, so your resultField variable is set to nil. The dictionary's value for the key responseData is another dictionary which does contain a key results -- you need that middle step.
Also, the value for the results key in that second dictionary is an array (of more dictionaries), not a dictionary itself.
There is no need to create a new dictionary each time. For easier reading I'd recommend something like:
[[dictionary objectForKey:#"responseData"] objectForKey:#"results"]
There you have the array of results. You can then add
[ [dictionary objec...] objectAtIndex:0]
I've got a question regarding parsing a JSON response within iOS5.
Currently, I'm following this guide here to help me parse the JSON response returned from a third-party mapping service.
Everything works, except that the JSON response returned by the third-party server is somewhat different from the one shown in the guide itself.
In a nutshell, the overall structure of the entire JSON response looks something like this:
{
"directions": [....],
"messages": [....],
"routes":
{
"features": [
{
"attributes": {....},
"geometry":
{
"paths": [....]
}
}
]
}
}
This is the actual JSON query URL.
By using this line of code,
NSDictionary * jsonResponse = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&error];
I am able to sucessfully get the jsonResponse dictionary to report that it has 3 key/value pairs, but my ultimate goal is to retrieve the array stored in 'routes.features.geometry.paths'.
This is my current code block that gets the final set of array values:
NSDictionary * jsonResponse = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&error];
NSArray * jsonArray = [jsonResponse valueForKeyPath:#"routes.features.geometry.paths"];
jsonArray = [jsonArray objectAtIndex:0];
jsonArray = [jsonArray objectAtIndex:0];
I was wondering if anyone might have a better idea of how I should go about doing this in a more elegant fashion?
Thanks a lot in advance!
You can't just use it as JSON object because it will be working as JSON (Plain String) and you need to parse it so for your problem you can do like this to directly go to paths
NSArray *arr = [[[[jsonResponse objectForKey:#"routes"] objectForKey:#"features"] objectForKey:#"geometry"] objectForKey:#"paths"];
Now you can access your paths data from "arr" array
UPDATE:
NSArray *arr = [[[[[jsonResponse objectForKey:#"routes"] objectForKey:#"features"] objectAtIndex:0] objectForKey:#"geometry"] objectForKey:#"paths"];
as features element is an Array so traverse array first then goto its elements