I'm searching Twitter for tweets with this code:
- (void)fetchTweets
{
NSURL *url = [NSURL URLWithString:#"http://search.twitter.com/search.json"];
NSDictionary *params = [NSDictionary dictionaryWithObject:#"#winning" forKey:#"q"];
TWRequest *request = [[TWRequest alloc] initWithURL:url
parameters:params
requestMethod:TWRequestMethodGET];
[request performRequestWithHandler:
^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
if (responseData) {
NSError *jsonError;
tweets =
[NSJSONSerialization JSONObjectWithData:responseData
options:kNilOptions
error:&jsonError];
if (tweets) {
// NSLog(#"%#", tweets);
}
else {
NSLog(#"%#", jsonError);
}
}
[[self delegate] receivedTweets];
}];
[self performSelector:#selector(fetchTweets) withObject:nil afterDelay:30];
The tweets variable is a NSArray and I am trying to put it into a NSDictionary with this code:
NSDictionary *tweet = [[TwitterHandler sharedInstance].tweets objectAtIndex:indexPath.row];
I am definitely getting the JSON text for the tweets but when trying to add them to the dictionary so I can eventually put them into a table I get the "unrecognized selector sent to instance" error.
I am not sure why I am getting this and any help would be appreciated.
In this code:
if (responseData) {
NSError *jsonError;
tweets =
[NSJSONSerialization JSONObjectWithData:responseData
options:kNilOptions
error:&jsonError];
if (tweets) {
// NSLog(#"%#", tweets);
}
else {
NSLog(#"%#", jsonError);
}
Is tweets the same that you are getting with this code:
[[TwitterHandler sharedInstance].tweets
If so, it seems to me that you are assigning it to au autoreleased object, so it will eventually be released and you will end-up with a pointer to a released object.
Better retain it or use a retain property when assigning it.
Something like
tweets =
[[NSJSONSerialization JSONObjectWithData:responseData
options:kNilOptions
error:&jsonError] retain];
or, assuming that tweets is a retain orpperty:
self.tweets =
[NSJSONSerialization JSONObjectWithData:responseData
options:kNilOptions
error:&jsonError];
Do not forget to release it when it is no longer needed (at least in the dealloc of your class)
EDIT
Ok, here is the thing, and it has nothing to do with memory management (wrong initial guess!): I tried your URL, and it returns:
{"error":"You must enter a query."}
Which is a JSon dictionary. Then the JSON Parser identifies this as a dictionary and returns you a dictionary. You may store it in a NSArray*, but the object instantiated is still a dictionary, and will only responds to the NSDictionary methods. As you comment shows when you print it, it prints a dictionary.
I had this once and it was the app releasing the view controller, check if your view controller is being released.
[NSJSONSerialization JSONObjectWithData:responseData
options:kNilOptions
error:&jsonError];
This returns an NSDictionary object of the tweets. The Twitter search results from that URL can be filtered out by looking for the content in the key results.
AKA:
NSDictionary *jsonTweet = [NSJSONSerialization JSONObjectWithData:responseData
options:kNilOptions
error:&jsonError];
NSArray *tweet = [jsonTweet objectForKey:#"results"];
Then the tweets can be iterated through since they are in an NSArray.
Related
NSString *connection = #"http:"(link);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
NSError *error = nil;
NSURL *url = [NSURL URLWithString:connection];
NSString *json = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error];
NSLog(#"\nJSON: %# \n Error: %#", json, error);
if(!error) {
NSData *jsonData = [json dataUsingEncoding:NSUTF8StringEncoding];
NSLog(#"%#",jsonData);
NSMutableArray *jsonDict = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:&error];
NSLog(#"JSON: %#", jsonDict);
}
});
The above code returns :
JSON: "{\"value\":[{\"Id\":\" }}
but
NSData is 69746963 735c222c 5c224973 41767469 76655c22 3a5c2231 5c222c
and jsonDict returns (null).
I am confused what may be going on.
Can somebody please help me figure it out.
I am trying to get the JSON data but it returns null.
Thanks
You say the server gave you this:
JSON: "{\"value\":[{\"Id\":\" }}
If I remove the backslashes that were added by the NSLog command, the actual JSON that you received was
{"value":[{"Id":" }}
That isn't valid JSON. That's all there is to it; the server sent you rubbish data, and there is no way to get any information from it. Contact the people creating the server software and ask them to fix the problem.
And you really, really need to distinguish between what an object really contains, and what NSLog prints. NSLog prints the contents of an NSData object by displaying each byte as two hexadecimal digits.
Try one of these (array or dictionary) without converting it into JSON, depending on what u want :
NSString *connection = #"http://(link)";
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
NSDictionary *jsonDict = [NSDictionary dictionaryWithContentsOfURL:[NSURL URLWithString:connection]];
NSArray *jsonArray = [NSArray arrayWithContentsOfURL:[NSURL URLWithString:connection]];
NSLog(#"DICT: %# ARRAY: %#", jsonDict, jsonArray);
});
I haven't tried it, please paste results?
By the look of your NSString response, it starts with { and ends with } which means it is a NSDictionary.
Change :
NSMutableArray *jsonDict = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:&error];
to :
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:jsonData options:nil error:&error];
So, i have a loop where i repeatedly call an url, which returns contacts in JSON format.
Since i call the url more than once, i want to add it all up, an ultimately end up with a NSDictionary, containing contacts for all the url calls.
What i'm doing now, is appending the data for each iteration:
NSData *response = [NSURLConnection sendSynchronousRequest:request
returningResponse:nil error:nil];
[data appendData:response];
and when the loop is over i try to make it into a NSDictionary:
// Loop over - create Dict from all the data.
NSDictionary *JSONDataFinal = [NSJSONSerialization JSONObjectWithData:data
options:0 error:&error2];
I get an error: "garbage at end" and believe the approach is wrong, since it doesn't know how to put data from each consecutive call into the same key, and not create a key for each call.
Should i create a Dictionary for each iteration - and combine them in the end?
You can append data to a NSMutableDictionary after each call.
NSMutableDictionary* jsonDict = [[NSMutableDictionary alloc] init];
for (...) {
...
NSData *response = [NSURLConnection sendSynchronousRequest:request
returningResponse:nil error:nil];
NSDictionary *JSONData = [NSJSONSerialization JSONObjectWithData:data
options:0 error:&error2];
[jsonDict addEntriesFromDictionary:JSONData];
}
Create different dictionary for each json data and store in main array like this:
NSMutableArray *arrAllContacts = [NSMutableArray array];
//here arrJsonURL which stores all url for contacts
for(int i=0; i<[arrJsonURL count]; i++)
{
//create request
...............
NSData *response = [NSURLConnection sendSynchronousRequest:request
returningResponse:nil error:nil];
[data appendData:response];
NSError *error = nil;
//get dictionary from json data
NSDictionary *dictContact = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
[arrAllContacts addObject:dictContact];
}
I'm having trouble parsing my JSON. The JSON is:
{"privatecode":"XDhUZQ1rA2gBZwshV2NrZQRnDmVPZQhuVj7WOlNrC29SPwg6VDUGelU1DahQNlc1AWpcPVBuWmc"}
I'm using following code:
id parsedObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:&localError];
The class of parsedObject is NSDictionary, but it contains the following error:
(<invalid>) [0] = <error: expected ']'
error: 1 errors parsing expression
>
Of course I could say:
NSDictionary *parsedObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:&localError];
but this makes no difference. I just want to get the privatecode as an NSString object, so what am I doing wrong and how can I fix this?
Many thanks in advance.
EDIT: Some more code I'm using:
NSLog(#"Response: %#", [request responseString]);
id parsedObject = [NSJSONSerialization JSONObjectWithData:[request responseData] options:0 error:&localError];
request is of type ASIHTTPRequest. The output of the log is:
Response: {"privatecode":"XDhUZQ1rA2gBZwshV2NrZQRnDmVPZQhuVj7WOlNrC29SPwg6VDUGelU1DahQNlc1AWpcPVBuWmc"}
Use this:
NSDictionary *parsedObject = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&localError];
I am using this for my project without any problem. Hope this helps. :)
EDIT:
From your error it seems that it is an array (array starts with '['). But your posted JSON is Dictionary (starts with '{'). It is weird. I searched and got this. Check this:
if ([returnedFromWeb respondsToSelector:#selector(objectAtIndex:)]) { // you can replace respondsToSelector:#selector(objectAtIndex:) by isKindOfClass:[NSArray class]
//it's an array do array things.
} else {
//it's a dictionary do dictionary things.
}
This worked for me, I was getting the same error you are but my response is an array. Since it looks like you are expecting a dictionary I'll include what that might look like.
id test = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:error];
NSArray *array;
NSDictionary *dictionary;
if ([test isKindOfClass:[NSArray class]]) {
//it's an array do array things.
array = [NSArray arrayWithArray:test];
} else {
//it's a dictionary do dictionary things.
dictionary = [NSDictionary dictionaryWithDictionary:test];
}
At this point you should be able to access the contents of the array or dictionary.
Simplified:
NSArray *array = [NSArray arrayWithArray:[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:error]];
OR
NSDictionary *dictionary = [NSDictionary dictionaryWithDictionary:[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:error]];
I have a WebService, which give me the fallowing Json-String back:
"{\"password\" : \"1234\", \"user\" : \"andreas\"}"
I call the webservice and try to parse the returned data like:
[NSURLConnection sendAsynchronousRequest: request
queue: queue
completionHandler: ^(NSURLResponse *response, NSData *data, NSError *error) {
if (error || !data) {
// Handle the error
} else {
// Handle the success
NSError *errorJson = nil;
NSDictionary *responseDict = [NSJSONSerialization JSONObjectWithData: data options: NSJSONReadingMutableContainers error: &errorJson];
NSString *usr = [responseDict objectForKey:#"user"];
}
}
];
But the resulting NSDictionary looks like:
What has the effect, that I cannot get the values - for example user.
Can someone help me, what I am doing wrong? - Thank you.
From the debugger screenshot is seems that the server is (for whatever reason) returning
"nested JSON": responseDict[#"d"] is a string containing JSON data again, so you have to
apply NSJSONSerialization twice:
NSError *errorJson = nil;
NSDictionary *responseDict = [NSJSONSerialization JSONObjectWithData: data options:0 error: &errorJson];
NSData *innerJson = [responseDict[#"d"] dataUsingEncoding:NSUTF8StringEncoding];
NSMutableDictionary *innerObject = [NSJSONSerialization JSONObjectWithData:innerJson options:NSJSONReadingMutableContainers error:&errorJson];
NSString *usr = [innerObject objectForKey:#"user"];
If you have the option, a better solution would be to fix the web service to return
proper JSON data.
My Json response is
[{"id":"1", "x":"1", "y":"2"},{"id":2, "x":"2", "y":"4"}]
And I did
NSString *response = [request responseString];
SBJSON *parser = [[SBJSON alloc] init];
NSArray *jsonObject = [parser objectWithString:response error:nil];
At this point I believe that jsonObject is a array that has two NSDictionary..
How can I make jsonObject that has two NSArray instead of NSDictionary?
What is the best way to do so? I think that I need to convert nested NSDictionary to NSArray?
I would use the NSJSONSerialization class now in the Foundation framework.
With the JSONObjectWithData method, it will return the type of container you want the data stored in at the top level. For example:
NSError *e;
NSArray *jsonObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:&e];
for (NSDictionary *dict in jsonObject) {
NSLog(#"json data:\n %#", dict);
// do stuff
}
Alternately, you could return a mutable container, such as:
NSMutableDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&e];
Here is the Apple documentation:
NSJSONSerialization