Want to split the JSON from the URL not the response - objective-c

I want to split the json part from this URL in my iPhone application.
http://vkontakte.ru/login_success.html#session={"expire":"1272008089","mid":"100172","secret":"9c8d8f0305","sid":"1131703552161ae352a1256402e3140d7cbde41b1602a93d15472c82"}
I tried and and saved the JSON into a NSString but what i am getting is
http://vkontakte.ru/api/login_success.html?session=%7B%22mid%22:113158415,%22secret%22:%227ce58bfcd3%22,%22sid%22:%2203831b43c1bb992f9477efbfe96e83f6ecff1c1b661315ac0a20719cf57a44%22,%22expire%22:0%7D
This is not coming in JSOn Format. Below is my code
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
NSURL *url = [request URL];
NSError* error;
NSLog (#"json path %#",url);
SBJsonParser *parser = [[SBJsonParser alloc] init];
NSURLRequest *request1 = [NSURLRequest requestWithURL:url];
NSString *json_string = [url absoluteString];
NSArray *arr = [json_string componentsSeparatedByString:#"="];
json_string = [arr objectAtIndex:1];
// parse the JSON response into an object
// Here we're using NSArray since we're parsing an array of JSON status objects
NSArray *statuses = [json_string JSONValue];
NSLog(#"%#",error);
// Each element in statuses is a single status
// represented as a NSDictionary
for (NSDictionary *status in statuses)
{
// You can retrieve individual values using objectForKey on the status NSDictionary
// This will print the tweet and username to the console
NSLog(#"%# - %#", [status objectForKey:#"secret "], [[status objectForKey:#"mid"] objectForKey:#"sid"]);
}
return YES;
}
How can move further?

Try replacing:
NSString *json_string = [url absoluteString];
with
NSString *json_string = [[url absoluteString] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];.
That's a really strange thing you're doing, though. Why does the URL have JSON in it?

Related

Error 400 and 415 when exchanging code for access_token

I am writing an application to authorise itself into Spotify. I used the node app.js example to get things working and an now re-writing natively into Objective C. I have extracted the authorisation code via a callback function
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"https://accounts.spotify.com/api/token"]];
request.HTTPMethod = #"POST";
// put in the header fields
NSString *headerString = [NSString stringWithFormat:#"%#:%#",clientID,clientSecret];
NSData *nsdata = [headerString dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64Encoded = [nsdata base64EncodedStringWithOptions:0];
base64Encoded = [ NSString stringWithFormat:#"Basic %#", base64Encoded];
[request setValue:base64Encoded forHTTPHeaderField:#"Authorization"];
NSLog(#"request.header %#", request.allHTTPHeaderFields.description);
// put in the body form
NSString * stringData = [NSString stringWithFormat:#"grant_type:%#, code:%#, redirect_uri:\"%#\"", #"authorization_code",authorisationCode,redirectUri];
NSData * requestBodyData = [stringData dataUsingEncoding:NSUTF8StringEncoding];
request.HTTPBody = requestBodyData;
NSLog(#"request.body %#", [[NSString alloc] initWithData:request.HTTPBody encoding:NSUTF8StringEncoding]);
I then post this request and get
{"error":"server_error","error_description":"Unexpected status: 415"}
returned.
I have found a variety of questions on this topic revolving around the Content-Type needing to be application/x-www-form-urlencoded but this was no direct cure.
Anyone got any suggestions for me?
I found the answer here NSURLRequest : Post data and read the posted page
It appears that the raw data within the HTTPBody needs to be formatted differently - no JSON at all. The above link has a useful function which I updated slightly
-(NSData*)encodeDictionary:(NSDictionary*)dictionary {
NSMutableArray *parts = [[NSMutableArray alloc] init];
for (NSString *key in dictionary) {
NSString *encodedValue = [[dictionary objectForKey:key] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPasswordAllowedCharacterSet]];
NSString *encodedKey = [key stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPasswordAllowedCharacterSet]];
NSString *part = [NSString stringWithFormat: #"%#=%#", encodedKey, encodedValue];
[parts addObject:part];
}
NSString *encodedDictionary = [parts componentsJoinedByString:#"&"];
return [encodedDictionary dataUsingEncoding:NSUTF8StringEncoding];
}
and ..
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
//NSLog(#"request.header %#", request.allHTTPHeaderFields.description);
// put in the body form using the new function
NSDictionary * parameters = [[NSDictionary alloc] initWithObjectsAndKeys:#"authorization_code",#"grant_type",authorisationCode,#"code",redirectUri,#"redirect_uri", nil ];
NSData * requestBodyData = [self encodeDictionary:parameters];
request.HTTPBody = requestBodyData;

Error with parsing JSON with NSJSONSerialization

I use openweathermap API to print current weather. I need to parse this JSON (JSON with available cities). I tried to parse it with NSJSONSerializer, but the answer was :"error NSError * domain: #"NSCocoaErrorDomain" - code: 3840".
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"city.list" ofType:#"json"];
NSString *myJSON = [[NSString alloc] initWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
NSError *error;
NSData *objectData = [myJSON dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:objectData options:NSJSONReadingMutableContainers error:&error];
As i understand, error 3840 says about wrong JSON format, but i have downloaded JSON from official openweathermap page. What's wrong? How parse this JSON correctly?
The file is no valid JSON, but a list of valid JSONs.
{"_id":707860,"name":"Hurzuf","country":"UA","coord":{"lon":34.283333,"lat":44.549999}}
{"_id":519188,"name":"Novinki","country":"RU","coord":{"lon":37.666668,"lat":55.683334}}
{"_id":1283378,"name":"Gorkhā","country":"NP","coord":{"lon":84.633331,"lat":28}}
…
Such a list in a valid JSON would look like this …:
[
{"_id":707860,"name":"Hurzuf","country":"UA","coord":{"lon":34.283333,"lat":44.549999}},
{"_id":519188,"name":"Novinki","country":"RU","coord":{"lon":37.666668,"lat":55.683334}},
{"_id":1283378,"name":"Gorkhā","country":"NP","coord":{"lon":84.633331,"lat":28}},
…
]
… or like this …
{
{"707860": {"name":"Hurzuf","country":"UA","coord":{"lon":34.283333,"lat":44.549999}},
{"519188": {"name":"Novinki","country":"RU","coord":{"lon":37.666668,"lat":55.683334}},
{"1283378":{"name":"Gorkhā","country":"NP","coord":{"lon":84.633331,"lat":28}},
…
However, what you can do is to iterate over the list and convert it item separately:
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"city.list" ofType:#"json"];
NSString *myList = [[NSString alloc] initWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
// Separate the lines
NSArray *myItems = [myList componentsSeperatedByCharactersInSet:[NSCharacterSet newLineCharacterSet];
NSError *error;
for( NSString *JSON in myItems )
{
if( [JSON length]==0)
{
// empty line
continue;
}
NSData *objectData = [JSON dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *object = [NSJSONSerialization JSONObjectWithData:objectData options:NSJSONReadingMutableContainers error:&error];
if( object == nil )
{
NSLog( #"Error %# reading\n%#", error, JSON);
}
}
Your json is not formatted correctly.
{"_id":707860,"name":"Hurzuf","country":"UA","coord":{"lon":34.283333,"lat":44.549999}}
{"_id":519188,"name":"Novinki","country":"RU","coord":{"lon":37.666668,"lat":55.683334}}
should be
[{"_id":707860,"name":"Hurzuf","country":"UA","coord":{"lon":34.283333,"lat":44.549999}},
{"_id":519188,"name":"Novinki","country":"RU","coord":{"lon":37.666668,"lat":55.683334}},
...]
Note the encapsulating square brackets and commas at the end.
Or you could parse the text line-by-line (it seems it is ment to be parsed like that).

Get web service response data

I have made this so far. It's code that will make a json String request with an http Header. When i run this code i get no errors. But i get a Expression result unused warning. I should get a response from the web service after sending this http header.
code:
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *nid = #"";
NSString *vocab = #"";
NSString *inturl = #"testoverview";
NSString *mail = #"chh#fbr.dk";
NSString *md5pw = #"4d57e7ef1b7c3f431aca424764e9d786";
NSDictionary *jsonDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
nid, #"nid",
vocab, #"vocab",
inturl, #"inturl",
mail, #"mail",
md5pw, #"md5pw",nil];
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonDictionary options:NSJSONWritingPrettyPrinted error:&error];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
if (!jsonData) {
NSLog(#"Got an error; %#", error);
} else if(jsonData) {
NSString *url = #"http://www.taenk.dk/services/mobile";
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url] cachePolicy:NSURLCacheStorageAllowed timeoutInterval:30.0];
[request setValue:jsonString forHTTPHeaderField:#"X-FBR-App"];
[[NSURLConnection alloc] initWithRequest:request delegate:self]; <-- this line triggers the warning: "Expression result unused"
NSLog(#"jsonString %#", jsonString);
}
Can anybody clarify 2 things for me:
Does this trigger a response as soon as the request to the web service?
If yes, how do i print this result out?
You need to assign the result to a variable like
NSURLConnection *con = [[NSURLConnection alloc] initWithRequest:...
for later use (e.g. [con cancel];)
Then you should at least implement the delegate method connection:didFailWithError:. In the class reference I don't see the connection:didFinishLoading... anymore. Can you use the sendSynchronousRequest:returningResponse:error: instead, then you'll have the result, be it positive or negative.
This is how I retrieved the data (this version is without ARC):
- (void) connection :(NSURLConnection *)conn didReceiveData :(NSData *)data {
NSString *msg = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
[self checkAutoMailReply:msg];
[msg release];
}
msg contains the pure response data, no header or such.

parse JSON in objectiveC (SBJSON) objects and arrays

So far I've discovered in JSON that everything enclosed in { } are objects (objC : NSDictionary) and anything enclosed in [ ] is an array (objC : NSArray).
I've read and re-read this article about the subject>
How to parse JSON into Objective C - SBJSON
I have a .json file with the data modeled like this:
http://elbee101.com/dummySchedule.json
...and now for the code:
SBJSON *parser = [[SBJSON alloc] init];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://elbee101.com/dummySchedule.json"]];
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSString *json_string = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
NSDictionary *schedule = [parser objectWithString:json_string error:nil];
NSDictionary *day = [schedule objectForKey:#"day"];
NSArray *myList = [day objectForKey:#"name"];
NSLog(#"myList %#", myList);
NSArray *numLaps = [myList objectAtIndex:0];
NSLog(#"numlaps%# ", numLaps);
I'm getting "myList (null)" and "numlaps (null)" from the above code?!#
The question: Can somebody please set me straight on the ordering of objects and arrays with respect to my json data? I want to drill down the tree so that I can access the 'day name', 'session starttime/endtime/sessionname', 'numlaps' & 'class' but I can't seem to get past the 'day' object/array(?)
What you're referring to as schedule is the object enclosed in the outermost {}. Try this:
NSDictionary *json = [parser objectWithString:json_string error:nil];
NSDictionary *schedule = [json objectForKey:#"schedule"];
Then continue as before.
Also, if you're on iOS 5 you can use the NSJSONSerialization class -- using it is pretty much the same, you might get better performance, and you don't have to worry about the hassles of using a third-party library.
call this where ever u need to parse
NSMutableArray *arr=[[NSMutableArray alloc] init];
arr=[[Headparse getArrayFromUrl:#"http://elbee101.com/dummySchedule.json"] retain];
NSLog(#"%#",[arr description]);
[arr release];
write this method as custom class use when ever you need
+(NSMutableArray *) getArrayFromUrl: (NSString *)actionType
{
NSMutableData *responseData1= [NSMutableData data] ;
responseData1 = [NSMutableData dataWithContentsOfURL:[NSURL URLWithString:actionType]];
// NSLog(#"%#",responseData1);
NSString *responseString1 = [[NSString alloc] initWithData:responseData1 encoding:NSUTF8StringEncoding];
//NSLog(#"REs:-->%#",responseString1);
//[responseData1 release];
responseData1 = nil;
NSMutableArray *responseArray = [[NSMutableArray alloc]init];
responseArray = (NSMutableArray *)[responseString1 JSONValue];
// NSLog(#"ghfchfvghv%#",responseArray);
[responseString1 release];
return responseArray;
}
This is how i use NSJsonSerialization for parsing the json object.
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://elbee101.com/dummySchedule.json"]];
NSError *err;
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:data
options:kNilOptions
error:&err]; //
NSDictionary *schedule_dict = [json objectForKey:#"schedule"];
NSArray *days = [schedule_dict objectForKey:#"day"];//Days Array from day Object
NSDictionary *dayOne = [days objectAtIndex:0];
NSDictionary *dayTwo = [days objectAtIndex:1];
NSLog(#"THE DAY ONE : %#",dayOne);
NSLog(#"THE DAY TWO : %#",dayTwo);
Hope this may help you ....Note : If you don't want to go with NSJsonSerailization(consider reading of this) ,but still the parsing of json data like above will applicable in your case too.

Parsing nested JSON objects with JSON Framework for Objective-C

I have the following JSON object:
{
"response": {
"status": 200
},
"messages": [
{
"message": {
"user": "value"
"pass": "value",
"url": "value"
}
]
}
}
I am using JSON-Framework (also tried JSON Touch) to parse through this and create a dictionary. I want to access the "message" block and pull out the "user", "pass" and "url" values.
In Obj-C I have the following code:
// Create new SBJSON parser object
SBJSON *parser = [[SBJSON alloc] init];
// Prepare URL request to download statuses from Twitter
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:myURL]];
// Perform request and get JSON back as a NSData object
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
// Get JSON as a NSString from NSData response
NSString *json_string = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
//Print contents of json-string
NSArray *statuses = [parser objectWithString:json_string error:nil];
NSLog(#"Array Contents: %#", [statuses valueForKey:#"messages"]);
NSLog(#"Array Count: %d", [statuses count]);
NSDictionary *results = [json_string JSONValue];
NSArray *tweets = [[results objectForKey:#"messages"] objectForKey:#"message"];
for (NSDictionary *tweet in tweets)
{
NSString *url = [tweet objectForKey:#"url"];
NSLog(#"url is: %#",url);
}
I can pull out "messages" and see all of the "message" blocks, but I am unable to parse deeper and pull out the "user", "pass", and "url".
Solved:
NSArray *tweets = [[results objectForKey:#"messages"] valueForKey:#"message"];
Array({
0=>Dictionary({
response = Array({
0=>Dictionary(Status = 200)
})
}),
1=>Dictionary({
messages = Array({
0=> Dictionary({
message = Array({
0=>Dictionary({
user = value,
pass=value,
url=value
})
})
})
})
})
})
So, to access dictionary for user, pass, url,
nsarray *arr = jsonmainarray;
arr = [[[jsonmainarray objectAtIndex: 1] objectforkey:#"messages"] objectatindex: 0];
nsdictionary *dict = [arr objectatindex: 0];
arr = [dict objectforkey:#"message"];
dict = [arr objectatindex: 0]; // Dictionary with user, pass, url
there is an easier way (in my opinion) to do JSON parsing :)
- (void)loadJSONData:(NSString *)u{
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"http://expandurl.appspot.com/expand?url=%#", u]];
NSData *rawJsonData = [NSData dataWithContentsOfURL:url];
CJSONDeserializer *parser = [CJSONDeserializer new];
NSError *error;
NSDictionary *jsonDictionary = [parser deserializeAsDictionary:rawJsonData error:&error];
[parser release];
NSArray *array = [jsonDictionary objectForKey:#"urls"];
}
All you have to do is to use JSON touch... like Sheehan Alam mention.
Say that you got this line of JSON data:
{
"end_url" = "http://www.youtube.com";
redirects = 0;
"start_url" = "http://www.youtube.com";
status = OK;
urls = (
"http://www.youtube.com"
);
}
then in your JSONDictonary the data can be accessed by doing:
[jsonDictionary objectForKey:#"urls"]; //This will return an Array since URLS is a array
[jsondictionary objectForKey:#"en_url"]; //this will return an NSString since end_url is a string
Hope this help people as much as it helped me =)
sincerely yours
Kristian