I'm making URL Request to an API but I dont know how to render the JSON, It generates an array of multiple users like this [{"user": "value"}, {"user":"value"}] and I was trying to use a TableView so I need an NSDictionary but i think is better to render a JSON like {users: [{"user": "value"}, {"user":"value"}]}. I have this code to make the request
#import "JSONKit.h"
NSError *error = nil;
NSURLResponse *response = nil;
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL: [NSURL URLWithString: #"http://localhost:3000/getusers"]];
[request setHTTPMethod:#"GET"];
NSData *jsonData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
users = [[jsonData objectFromJSONData] objectForKey:#"users"];
usersKeys = [users allKeys];
but I'm getting this error
2012-09-16 18:51:11.360 tableview[2979:c07] -[JKArray allKeys]: unrecognized selector sent to instance 0x6d30180
2012-09-16 18:51:11.362 tableview[2979:c07] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[JKArray allKeys]: unrecognized selector sent to instance 0x6d30180'
I dont really know how to accomplish this so any help is useful, thanks
You are getting that error because whatever got parsed out of "jsonData" isn't necessarily what you expected (i.e. a dictionary).
Perhaps you need some error checking in that code of yours.
For example:
NSData *jsonData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
if(jsonData)
{
id objectReturnedFromJSON = [jsonData objectFromJSONData];
if(objectReturnedFromJSON)
{
if([objectReturnedFromJSON isKindOfClass:[NSDictonary class]])
{
NSDictionary * dictionaryFromJSON = (NSDictionary *)objectReturnedFromJSON;
// assuming you declared "users" & "usersKeys" in your interface,
// or somewhere else in this method
users = [dictionaryFromJSON objectForKey:#"users"];
if(users)
{
usersKeys = [users allKeys];
} else {
NSLog( #"no users in the json data");
}
} else {
NSLog( #"no dictionary from the data returned by the server... check the data to see if it's valid JSON");
}
} else {
NSLog( #"nothing valid returned from the server...");
}
} else {
NSLog( #"no data back from the server");
}
I was thinking on something like this
NSError *error = nil;
NSURLResponse *response = nil;
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL: [NSURL URLWithString: #"http://localhost:3000/getusers"]];
[request setHTTPMethod:#"GET"];
NSData *jsonData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
JSONDecoder *decoder = [[JSONDecoder alloc]
initWithParseOptions:JKParseOptionNone];
NSArray *json = [decoder objectWithData:jsonData];
NSMutableArray *objects = [[NSMutableArray alloc] init];
NSMutableArray *keys = [[NSMutableArray alloc] init];
for (NSDictionary *user in json) {
[objects addObject:[user objectForKey:#"user" ]];
[keys addObject:[user objectForKey:#"value" ]];
}
users = [[NSDictionary alloc] initWithObjects:objects forKeys:keys];
NSLog(#"users: %#", users);
usersKeys = [users allKeys];
But it doesnt look efficient for many items or im wrong?
Related
Unable to parse this json data to object. Same code i tried with other URL, working correct. Please Suggest where i am doing wrong?
-(void)callAPI{
NSData *data=[NSData dataWithContentsOfURL:[NSURL URLWithString:#"https:s.json"]];
NSError *error=nil;
id response=[NSJSONSerialization JSONObjectWithData:data options:
NSJSONReadingMutableContainers | NSJSONReadingMutableLeaves error:&error];
if (error) {
NSLog(#"%#",[error localizedDescription]);
} else {
NSLog(#"%#",response);}}
Output The data couldn’t be read because it isn’t in the correct format.
I got the very perfect solution for your question which works fine now.Please check the below answer
- (void)callAPI
{
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setHTTPMethod:#"GET"];
[request setURL:[NSURL URLWithString:#"https://dl.dropboxusercontent.com/s/2iodh4vg0eortkl/facts.json"]];
[[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:
^(NSData * data,
NSURLResponse * response,
NSError * error) {
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSLog(#"jsonString is: %#", jsonString);
NSData *dataCon = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
id jsonVal = [NSJSONSerialization JSONObjectWithData:dataCon options:0 error:nil];
if([jsonVal isKindOfClass:[NSDictionary class]]) {
NSLog(#"The response starts with NSDictionary");
NSArray *arrJsonVal = [jsonVal objectForKey:#"rows"];
NSMutableArray *arrTitle = [[NSMutableArray alloc]init];
NSMutableArray *arrDesc = [[NSMutableArray alloc]init];
NSMutableArray *arrImage = [[NSMutableArray alloc]init];
for(NSDictionary *dict in arrJsonVal) {
NSString *strTitle = [dict objectForKey:#"title"];
NSString *strDesc = [dict objectForKey:#"description"];
NSString *strImage = [dict objectForKey:#"imageHref"];
[arrTitle addObject:strTitle];
[arrDesc addObject:strDesc];
[arrImage addObject:strImage];
}
NSLog(#"arrTitle is - %#",arrTitle);
NSLog(#"arrDesc is - %#",arrDesc);
NSLog(#"arrImage is - %#",arrImage);
}else {
NSLog(#"The response starts with NSArray");
}
}] resume];
}
The Printed results are
After that
Then Array results are
Finally the results are
I'm trying to build an app on the Feedly API. In order to be able to mark categories as read, I need to post some data to the API. I'm having no success, though.
This is what the API needs as input:
{
"lastReadEntryId": "TSxGHgRh4oAiHxRU9TgPrpYvYVBPjipkmUVSHGYCTY0=_1449255d60a:22c3491:9c6d71ab",
"action": "markAsRead",
"categoryIds": [
"user/c805fcbf-3acf-4302-a97e-d82f9d7c897f/category/design",
"user/c805fcbf-3acf-4302-a97e-d82f9d7c897f/category/photography"
],
"type": "categories"
}
And this is my method:
- (void)markCategoryAsRead: (NSString*)feedID{
NSLog(#"Feed ID is: %#", feedID);
NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults];
NSString *accessToken = [standardUserDefaults objectForKey:#"AccessToken"];
NSString *feedUrl = [NSURL URLWithString:#"https://sandbox.feedly.com/v3/markers"];
NSError *error = nil;
NSDictionary *tmp = [[NSDictionary alloc] initWithObjectsAndKeys:
#"markAsRead", #"action",
#"categories", #"type",
#[feedID], #"categoryIds",
#"1367539068016", #"asOf",
nil];
NSData *postdata = [NSJSONSerialization dataWithJSONObject:tmp options:0 error:&error];
NSLog(#"Postdata is: %#", postdata);
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:feedUrl];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-type"];
[request addValue:accessToken forHTTPHeaderField:#"Authorization"];
//[NSURLRequest setAllowsAnyHTTPSCertificate:YES forHost:[url host]];
NSError *errror = [[NSError alloc] init];
NSHTTPURLResponse *response = nil;
NSData *urlData=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&errror];
NSLog(#"Response code: %ld", (long)[response statusCode]);
if ([response statusCode] >= 200 && [response statusCode] < 300)
{
NSLog(#"It's marked as read.");
} else {
if (error) NSLog(#"Error: %#", errror);
NSLog(#"No success marking this as read. %#", response);
}
}
It keeps throwing a 400 error though, saying bad input. What am I doing wrong?
You're not doing anything with postdata after creating it. Attach it to the request.
[request setHTTPBody:postData];
There are a few problems in your code. Here are some I noticed:
You're not using postData.
The dictionary you make in tmp doesn't look like the dictionary you said you wanted to send. Where's lastReadEntryId, for example?
NSString *feedUrl should be NSURL *feedUrl
Stylistically, you should be using the dictionary literal syntax to create your dictionary. This will make it easier to debug.
So I understand how to split the array that holds the JSON info, but what I am stuck on is trying to get it to display everything past only the first whitespace. For instance, if you look at the JSON site (http://iam.colum.edu/portfolio/api/course?json=True) each course has a course number at beginning. I want to split each array object only displaying the course name. For instance, if you look at the site, the first object is "Computer Architecture" second is "Digital Image and Design"... etc. I don't need to know how to split the string, I can already do that, but how do I split it so it takes away "xx-xxx " (x being the course number)? The code I have currently splits at each whitespace, but that's not going to work for obvious reasons.
JSONViewController
dispatch_async(progressQueue, ^{
jstring = [JSONHelper JSONgetString:#"http://iam.colum.edu/portfolio/api/course?json=True"];
dispatch_async(dispatch_get_main_queue(), ^{
//main thread code
//textView.text = jstring;
jarray = [jstring componentsSeparatedByString:#" "];
textView.text = [jarray objectAtIndex:1];
NSString * fullString = [NSString string];
for(int i = 0; i < jarray.count; i++)
{
fullString = [fullString stringByAppendingString:[jarray objectAtIndex:i]];
}
textView.text = fullString;
NSError *error = nil;
NSArray * resultArray = [NSJSONSerialization JSONObjectWithData: [jstring dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableContainers error: &error];
if ( !resultArray ) {
NSLog(#"Error parsing JSON: %#", error);
} else {
for(NSString * course in resultArray) {
NSLog(#"Course: %#", course);
}
}
JSONHelper.h
#interface JSONHelper : NSObject
+ (NSDictionary *)JSONget:(NSString *)query;
+ (NSString *)JSONgetString:(NSString *)query;
+ (NSString *)JSONpostString:(NSString *)query;
+(NSString *)JSONpostString:(NSString *)query
withData:(NSString *)jsonData;
#end
JSONHelper.m
#implementation JSONHelper
//returns a dictionar from a get request
+ (NSDictionary *)JSONget:(NSString *)query
{
NSData *jsonData = [[NSString stringWithContentsOfURL:[NSURL URLWithString:query] encoding:NSUTF8StringEncoding error:nil] dataUsingEncoding:NSUTF8StringEncoding];
NSError *error = nil;
NSDictionary *results = jsonData ? [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error] : nil;
if (error) NSLog(#"[%# %#] JSON error: %#", NSStringFromClass([self class]), NSStringFromSelector(_cmd), error.localizedDescription);
return results;
}
//returns JSON string from get request
+(NSString *)JSONgetString:(NSString *)query
{
NSString* searchURL = [NSString stringWithFormat:query];
NSError* error = nil; //error for NSUSRLConnection
NSURLResponse* response = nil;
NSMutableURLRequest* request = [[NSMutableURLRequest alloc] init];
NSURL* URL = [NSURL URLWithString:searchURL];
[request setURL:URL];
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
[request setTimeoutInterval:30];
NSData* data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
if (error)
{
NSLog(#"Error performing request %#", searchURL);
return 0;
}
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"jsonString:%#", jsonString);
return jsonString;
}
+(NSString *)JSONpostString:(NSString *)query{
NSString* searchURL = [NSString stringWithFormat:query];
NSError* error = nil;
NSURLResponse* response = nil;
NSMutableURLRequest* request = [[NSMutableURLRequest alloc] init];
NSURL* URL = [NSURL URLWithString:searchURL];
[request addValue: #"application/json" forHTTPHeaderField:#"Accept"];
[request addValue: #"application/json" forHTTPHeaderField:#"Content-Type"];
[request setHTTPMethod:#"POST"];
[request setURL:URL];
[request setTimeoutInterval:15];
NSData* data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
if (error)
{
NSLog(#"Error performing request %#", searchURL);
return 0;
}
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"jsonString:%#", jsonString);
return jsonString;
}
+(NSString *)JSONpostString:(NSString *)query
withData:(NSString *)jsonData
{
NSString* searchURL = [NSString stringWithFormat:query];
NSError* error = nil;
NSURLResponse* response = nil;
NSMutableURLRequest* request = [[NSMutableURLRequest alloc] init];
NSURL* URL = [NSURL URLWithString:searchURL];
[request addValue: #"application/json" forHTTPHeaderField:#"Accept"];
[request addValue: #"application/json" forHTTPHeaderField:#"Content-Type"];
[request setHTTPMethod:#"POST"];
[request setURL:URL];
[request setTimeoutInterval:30];
NSData* requestData = [jsonData dataUsingEncoding:NSUTF8StringEncoding];
[request addValue:[NSString stringWithFormat:#"%d", [requestData length]] forHTTPHeaderField:#"Content-Length"];
[request setHTTPBody:requestData];
NSData* data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
if (error)
{
NSLog(#"Error performing request %#", searchURL);
return 0;
}
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"jsonString:%#", jsonString);
return jsonString;
}
#end
NSDictionary *dictionary = [JSONHelper JSONget:#"http://iam.colum.edu/portfolio/api/course?json=True"];
for (id course in dictionary) {
NSLog(#"%#", [course substringFromIndex:8]);
}
As you can seen all those course number has the same pattern (so I assume that won't change) and it's xx-xxxx (7 character + whitespace after this). In that cas you can easily use substring fromthe index 8 (counting from 0).
Bu if you are still eager on how to do this in case when those course numbers may have various lengths yo can try using this solution:
NSDictionary *dictionary = [JSONHelper JSONget:#"http://iam.colum.edu/portfolio/api/course?json=True"];
for (id course in dictionary) {
NSArray *courseArray = [course componentsSeparatedByString:#" "];
NSMutableString *courseName = [NSMutableString string];
for (int i = 1; i < [courseArray count] ; i++) {
[courseName appendFormat:#"%# ", courseArray[i]];
}
// Deleting last character which is whitespace
[courseName substringToIndex:courseName.length -1];
NSLog(#"%#", courseName);
[courseName setString:#""];
}
It may not be the most efficent way to handle your problem but it just works!
I'm trying to get the list of friends from twitter.
I'm trying this code: But i receive a NSDictionary with 5 keys: Next cursor, previous cursors, next cursor str, previous cursor str and users: the key user has 20 objects in value..but all are empty...
Whats wrong?
-(void) obterInformacoesTwitter {
NSURL *url = [NSURL URLWithString:#"https://api.twitter.com/1.1/friends/list.json"];
NSMutableDictionary *parameters = [[NSMutableDictionary alloc] init];
[parameters setObject:_contaSelecionada.username forKey:#"screen_name"];
NSLog(#"Screen name %#", _contaSelecionada.username);
TWRequest *request = [[TWRequest alloc] initWithURL:url parameters:parameters requestMethod:TWRequestMethodGET];
request.account = _contaSelecionada;
[request performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error)
{
if (responseData) {
NSError *error = nil;
NSDictionary* dict = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableLeaves error:&error];
NSArray *dictArray = [dict valueForKey:#"users"];
if([dict objectForKey:#"error"]!=nil)
{
}
else
{
}
}
}];
[parameters release];
[request release];
}
Have you tried if the JSON valid? With some online JSON viewers, I get:
JSON data URL inaccessable.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
My Code for NSURLConnection with sendSynchronousRequest works fine but how can i change it to an async request? i tried a lot but nothing would work.
if the Request is empty i´ll get an empty Array with [[]] .
How can i catch it for an Alert Message?
Please help ...
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSString *urlString = #"http://www.xyz.at/sample.php";
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:url];
[request setHTTPMethod:#"POST"];
NSMutableData *body = [NSMutableData data];
NSString *postWerte = [NSString stringWithFormat:#"id=%#", self.textfeld.text];
[body appendData:[postWerte dataUsingEncoding:NSUTF8StringEncoding]];
[request setHTTPBody:body];
NSError *error = nil;
NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&error];
NSLog(#"Error: %#", error.description);
NSString *returnString = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding];
const char *convert = [returnString UTF8String];
NSString *responseString = [NSString stringWithUTF8String:convert];
NSMutableArray *meinErgebnis = [responseString JSONValue];
NSString *cycle = #"";
NSString *kopfdaten = [NSString stringWithFormat:#"Sendungsart: %#\r\nGewicht: %# kg\r\n\r\n", [[meinErgebnis objectAtIndex:0] objectForKey:#"ParcelTypeDescription"], [[meinErgebnis objectAtIndex:0] objectForKey:#"Weight"]];
cycle = [cycle stringByAppendingString:kopfdaten];
for(int i = 1; i < meinErgebnis.count; i++)
{
NSString *myValue = [NSString stringWithFormat:#"%# PLZ: %#\r\nStatus: %#\r\n\r\n",
[[meinErgebnis objectAtIndex:i] objectForKey:#"EventTimestamp"],
[[meinErgebnis objectAtIndex:i] objectForKey:#"EventPostalCode"],
[[meinErgebnis objectAtIndex:i] objectForKey:#"ParcelEventReasonDescription"]];
cycle = [cycle stringByAppendingString:myValue];
}
self.ergebnis.text = [NSString stringWithFormat:#"%#", cycle];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
[self.textfeld resignFirstResponder];
You could:
create an NSOperationQueue, and
call sendAsynchronousRequest, placing all of your NSData processing code inside the completion block.
Thus, instead of:
NSURLResponse *response = nil;
NSError *error = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
// now process resulting `data`
Use:
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
// now process resulting `data`
}];
Alternatively, you could implement the NSURLConnectionDataDelegate methods. For more information on that, see the Using NSURLConnection section of the URL Loading System Programming Guide.
You say "if the request is empty": I assume you mean "if the data returned is empty". And you say it is [[]]. If that's really what you're getting, it sounds like an array with one item (which itself, is an empty array). Or is it [] (which is an empty array)? Or is it nil?
I'm going to assume that the data returned was [], an empty array.
I'd also suggest you consider using NSJSONSerialization, the built in JSON parser, but obviously you can use JSONValue if you really want.
Finally, your implementation is skipping the first entry (NSArray uses a zero-based index). I'm assuming that was unintentional.
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (error) {
NSLog(#"%s: sendAsynchronousRequest error: %#", __FUNCTION__, error);
return;
}
NSError *parseError;
NSArray *meinErgebnis = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
if (parseError) {
NSLog(#"%s: JSONObjectWithData error: %#", __FUNCTION__, parseError);
return;
}
if ([meinErgebnis count] == 0) {
NSLog(#"%s: meinErgebnis empty", __FUNCTION__);
return;
}
for (NSDictionary *dictionary in meinErgebnis)
{
// now process each dictionary entry in meinErgebnis
}
// etc.
}];