JSON ObjectiveC - Error - objective-c

Receiving the following error. I believe it has to do with the NSDictionary in the results of JSON array. I.e. NSDictionary within an NSDictionary maybe?
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString objectForKey:]: unrecognized selector sent to instance 0x7f9298554560'
This is the JSON service when called. This is printed directly out of XCode but it looks clean to me.
Printing description of self->metArray:
{
weatherObservation = {
ICAO = YBBN;
clouds = "few clouds";
cloudsCode = FEW;
countryCode = AU;
datetime = "2014-11-24 03:00:00";
dewPoint = 20;
elevation = 5;
hectoPascAltimeter = 1014;
humidity = 61;
lat = "-27.38333333333333";
lng = "153.1333333333333";
observation = "YBBN 240300Z 02019KT 9999 FEW029 SCT250 28/20 Q1014";
stationName = "Brisbane Airport M. O";
temperature = 28;
weatherCondition = "n/a";
windDirection = 20;
windSpeed = 19;
};
}
This is the code that invokes the JSON service.
-(void)getMetar{
// NSString *location = #"YBBN";
NSString * const metarUrl =#"http://api.geonames.org/weatherIcaoJSON?ICAO=YBBN&username=demo";
NSURL *url2 = [NSURL URLWithString:metarUrl];
NSData *data2 = [NSData dataWithContentsOfURL:url2];
metArray = [NSJSONSerialization JSONObjectWithData:data2 options:kNilOptions error:nil];
//Create an NSDictionary for the weather data to be stored.
NSDictionary *metarJson = [NSJSONSerialization JSONObjectWithData:data2 options:kNilOptions error:nil];
//Loop through the JSON array
NSArray *currentMetarArray = metarJson[#"weatherObservation"];
//set up array and json call
metarArray = [[NSMutableArray alloc]init];
for (NSDictionary *metaritem in currentMetarArray)
{
//create our object
NSString *nClouds = [metaritem objectForKey:#"clouds"];
NSString *nObservation = [metaritem objectForKey:#"observation"];
//Add the object to our animal array
[metarArray addObject:[[metar alloc]initWithclouds:(nClouds) andobservation:nObservation]];
}
}
It looks okay to me but maybe that is because I have been looking at it for hours.
Any ideas?

NSArray *currentMetarArray = metarJson[#"weatherObservation"];
for (NSDictionary *metaritem in currentMetarArray)
These lines are wrong. currentMetarArray is a dictionary, not array, it contains string key & value, so you should access it like in following way-
NSDictionary *jsonDictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
NSDictionary *weatherObservation = [jsonDictionary objectForKey:#"weatherObservation"];
then to get nCloud, use like
NSString *nClouds = [weatherObservation objectForKey:#"clouds"];

I go to your URL and get this message {"status":{"message":"the daily limit of 30000 credits for demo has been exceeded. Please use an application specific account. Do not use the demo account for your application.","value":18}}
But you can try my code, it worked for me
NSString *strUrl = #"http://api.geonames.org/weatherIcaoJSON?ICAO=YBBN&username=demo";
NSURL *url = [NSURL URLWithString:strUrl];
NSData *data = [NSData dataWithContentsOfURL:url];
NSError *error;
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
NSDictionary *weatherObservation = [json objectForKey:#"status"];
for (id key in weatherObservation) {
id value = [weatherObservation objectForKey:key];
NSLog(#"key = %#, value = %#", key, value);
}

The error thrown is the best clue for how you can fix this.
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString objectForKey:]: unrecognized selector sent to instance 0x7f9298554560'
What this means is that you're thinking an object is a dictionary when in reality it isn't.
You can combat this using NSObject methods such as:
[myObject respondsToSelector:(#selector(objectForKey:))]; // will return a boolean value.
to see if the object will respond to the method you hope to send it
or
[myObject isKindOfClass:[NSDictionary class]]; // will return a boolean value.
to determine if the object is a NSDictionary.
What's likely happening, though, is that you have an error in expectation with the Deserialized JSON Data.
Happy bug hunting!

Related

how to convert an array into string? [duplicate]

In my iPhone aplication I have a list of custom objects. I need to create a json string from them. How I can implement this with SBJSON or iPhone sdk?
NSArray* eventsForUpload = [app.dataService.coreDataHelper fetchInstancesOf:#"Event" where:#"isForUpload" is:[NSNumber numberWithBool:YES]];
SBJsonWriter *writer = [[SBJsonWriter alloc] init];
NSString *actionLinksStr = [writer stringWithObject:eventsForUpload];
and i get empty result.
This process is really simple now, you don't have to use external libraries,
Do it this way, (iOS 5 & above)
NSArray *myArray;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:myArray options:NSJSONWritingPrettyPrinted error:&error];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
I love my categories so I do this kind of thing as follows
#implementation NSArray (Extensions)
- (NSString*)json
{
NSString* json = nil;
NSError* error = nil;
NSData *data = [NSJSONSerialization dataWithJSONObject:self options:NSJSONWritingPrettyPrinted error:&error];
json = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
return (error ? nil : json);
}
#end
Although the highest voted answer is valid for an array of dictionaries or other serializable objects, it's not valid for custom objects.
Here is the thing, you'll need to loop through your array and get the dictionary representation of each object and add it to a new array to be serialized.
NSString *offersJSONString = #"";
if(offers)
{
NSMutableArray *offersJSONArray = [NSMutableArray array];
for (Offer *offer in offers)
{
[offersJSONArray addObject:[offer dictionaryRepresentation]];
}
NSData *offersJSONData = [NSJSONSerialization dataWithJSONObject:offersJSONArray options:NSJSONWritingPrettyPrinted error:&error];
offersJSONString = [[NSString alloc] initWithData:offersJSONData encoding:NSUTF8StringEncoding] ;
}
As for the dictionaryRepresentation method in the Offer class:
- (NSDictionary *)dictionaryRepresentation
{
NSMutableDictionary *mutableDict = [NSMutableDictionary dictionary];
[mutableDict setValue:self.title forKey:#"title"];
return [NSDictionary dictionaryWithDictionary:mutableDict];
}
Try like this Swift 2.3
let consArray = [1,2,3,4,5,6]
var jsonString : String = ""
do
{
if let postData : NSData = try NSJSONSerialization.dataWithJSONObject(consArray, options: NSJSONWritingOptions.PrettyPrinted)
{
jsonString = NSString(data: postData, encoding: NSUTF8StringEncoding)! as String
}
}
catch
{
print(error)
}
Try like this,
- (NSString *)JSONRepresentation {
SBJsonWriter *jsonWriter = [SBJsonWriter new];
NSString *json = [jsonWriter stringWithObject:self];
if (!json)
[jsonWriter release];
return json;
}
then call this like,
NSString *jsonString = [array JSONRepresentation];
Hope it will helps you...
I'm a bit late to this party, but you can serialise an array of custom objects by implementing the -proxyForJson method in your custom objects. (Or in a category on your custom objects.)
For an example.

How to parse multiple json in objective-c?

I am trying to parse JSON in objective-c but am having trouble. The example in the tutorial I am following only goes to the first level after the parent node. I am trying to get data that is a bit deeper. Any advice on how to do this?
The elements I am trying to get:
Title: data.children[i].data.title
Thumbnail: data.children[i].data.thumbnail
Json: http://www.reddit.com/r/HistoryPorn/.json
NSURL *blogURL = [NSURL URLWithString:#"http://www.reddit.com/r/HistoryPorn/.json"];
NSData *jsonData = [NSData dataWithContentsOfURL:blogURL];
NSError * error = nil;
NSDictionary *dataDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
self.blogPosts = [NSMutableArray array];
NSArray * blogPostsArray = [dataDictionary objectForKey:#"data"];
for (NSDictionary *bpDictionary in blogPostsArray) {
BlogPost * blogPost = [BlogPost blogPostWithTitle:[bpDictionary objectForKey:#"title"]];
blogPost.thumbnail = [bpDictionary objectForKey:#"thumbnail"];
blogPost.url = [NSURL URLWithString:[bpDictionary objectForKey:#"url"]];
[self.blogPosts addObject:blogPost];
}
With the new syntax it should be easier to gets keys in a nested dictionaries. You can know the full keys/indexes path by just drawing a tree, remember that a dictionary starts with braces, and an array starts with brackets. For example let's retrieve the "thumbnail" and "url" value for the first entry in the children array:
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
if(!json)
{
// Always handle eventual errors:
NSLog(#"%#",error);
return;
}
NSString* thumbnail= json[#"data"][#"children"][0][#"data"][#"thumbnail"];
NSString* url= json[#"data"][#"children"][0][#"data"][#"url"];

NSCFString objectAtIndex: unrecognized selector sent to instance Objective C [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I am trying to get some json data and show it as text in a UILabel but I keep on getting a app crash with the following error -[__NSCFString objectAtIndex:]: unrecognized selector sent to instance 0x1f8cfff0?
Here is my code and the json response. I see in my log that I am getting the Name from the call but the app bombs out the that error. I have 2 UILabel blocks, one of which shows a text format of the json response and the other the actual json response in text.
I'm trying to pull the name of the person, I can see Bilbo Baggins in the log when the json comes back.
Here is my json output:
{"ProfileID":34,"ProfilePictureID":20,"Name":"Bilbo Baggins","Clients":[{"ClientID":91,"Name":"Fnurky"},{"ClientID":92,"Name":"A different client"},{"ClientID":95,"Name":"Second Community"},{"ClientID":96,"Name":"Britehouse"}]}
and my code to try show it as a uilabel as text.
#define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) //1
#define kLatestKivaLoansURL [NSURL URLWithString: #"http://www.ddproam.co.za/Central/Profile/JSONGetProfileForUser"] //2
#import "JsonViewController.h"
#interface NSDictionary(JSONCategories)
+(NSDictionary*)dictionaryWithContentsOfJSONURLString:(NSString*)urlAddress;
-(NSData*)toJSON;
#end
#implementation NSDictionary(JSONCategories)
+(NSDictionary*)dictionaryWithContentsOfJSONURLString:(NSString*)urlAddress
{
NSData* data = [NSData dataWithContentsOfURL: [NSURL URLWithString: urlAddress] ];
__autoreleasing NSError* error = nil;
id result = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
if (error != nil) return nil;
return result;
}
-(NSData*)toJSON
{
NSError* error = nil;
id result = [NSJSONSerialization dataWithJSONObject:self options:kNilOptions error:&error];
if (error != nil) return nil;
return result;
}
#end
#implementation JsonViewController
- (void)viewDidLoad
{
[super viewDidLoad];
dispatch_async(kBgQueue, ^{
NSData* data = [NSData dataWithContentsOfURL: kLatestKivaLoansURL];
[self performSelectorOnMainThread:#selector(fetchedData:) withObject:data waitUntilDone:YES];
});
}
- (void)fetchedData:(NSData *)responseData {
//parse out the json data
NSError* error;
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:responseData //1
options:kNilOptions
error:&error];
NSArray* defineJsonData = [json objectForKey:#"Name"]; //2
NSLog(#"Name: %#", defineJsonData); //3
// 1) Get the latest loan
NSDictionary* loan = [defineJsonData objectAtIndex:0];
// 3) Set the label appropriately
humanReadble.text = [NSString stringWithFormat:#"Hello: %#",
[(NSDictionary*)[loan objectForKey:#"Name"] objectForKey:#"Name"]];
//build an info object and convert to json
NSDictionary* info = [NSDictionary dictionaryWithObjectsAndKeys:
[loan objectForKey:#"Name"],
nil];
//convert object to data
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:info
options:NSJSONWritingPrettyPrinted
error:&error];
//print out the data contents
jsonSummary.text = [[NSString alloc] initWithData:jsonData
encoding:NSUTF8StringEncoding];
}
#end
A combination of – sorry – poor var names and lost in a complex structure.
First:
Here you get the complete JSON as Dictionary:
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:responseData //1
options:kNilOptions
error:&error];
According to your Q, this has this structure:
{
"ProfileID":34,
"ProfilePictureID":20,
"Name":"Bilbo Baggins",
"Clients":
[
{
"ClientID":91,
"Name":"Fnurky"
},
{
"ClientID":92,
"Name":"A different client"
},
{
"ClientID":95,
"Name":"Second Community"
},
{
"ClientID":96,
"Name":"Britehouse"
}
]
}
Second:
With the next statement, you simply get the name of obviously something like a person:
NSArray* defineJsonData = [json objectForKey:#"Name"]; //2
There is the root:
what you get – look at your JSON – is:
"Name":"Bilbo Baggins",
You get the object for the key Name. The var, holding the reference to the result should be called expressing this. Let's change this:
NSArray* name = [json objectForKey:#"Name"]; //2
Next – look at your JSON – the object behind that key is an instance of NSString, not NSArray. Let's repair this:
NSString* name = [json objectForKey:#"Name"]; //2
Third:
Doing so will the compiler make throwing out an error. This is because of this statement:
NSDictionary* loan = [defineJsonData objectAtIndex:0];
Changed to the new var name:
NSDictionary* loan = [name objectAtIndex:0];
The compiler is right: You do not have an array, so you cannot send objectAtIndex:.

JSON and 2D array

The following is encoded JSON data from a PHP webpage.
{
{
"news_date" = "2011-11-09";
"news_id" = 5;
"news_imageName" = "newsImage_111110_7633.jpg";
"news_thread" = "test1";
"news_title" = "test1 Title";
},
{
"news_date" = "2011-11-10";
"news_id" = 12;
"news_imageName" = "newsImage_111110_2060.jpg";
"news_thread" = "thread2";
"news_title" = "title2";
},
// and so on...
}
I'd like to grab one buch of info (date/id/image/thread/title), and store it as an instance of a class. However, I have no clue on how to access each object in 2D arrays.
The following is the code I've written to test if I can access them, but it doesn't work.
What would be the problem?
NSURL *jsonURL = [NSURL URLWithString:#"http://www.sangminkim.com/UBCKISS/category/news/jsonNews.php"];
NSString *jsonData = [[NSString alloc] initWithContentsOfURL:jsonURL];
SBJsonParser *parser = [[SBJsonParser alloc] init];
contentArray = [parser objectWithString:jsonData];
NSLog(#"array: %#", [[contentArray objectAtIndex:0] objectAtIndex:0]); // CRASH!!
In JSON terminology, that’s not a two-dimensional array: it’s an array whose elements are objects. In Cocoa terminology, it’s an array whose elements are dictionaries.
You can read them like this:
NSArray *newsArray = [parser objectWithString:jsonData];
for (NSDictionary *newsItem in newsArray) {
NSString *newsDate = [newsItem objectForKey:#"news_date"];
NSUInteger newsId = [[newsItem objectForKey:#"news_id"] integerValue];
NSString *newsImageName = [newsItem objectForKey:#"news_imageName"];
NSString *newsThread = [newsItem objectForKey:#"news_thread"];
NSString *newsTitle = [newsItem objectForKey:#"news_title"];
// Do something with the data above
}
You gave me a chance to checkout iOS 5 Native JSON parser, so no external libraries needed, try this :
-(void)testJson
{
NSURL *jsonURL = [NSURL URLWithString:#"http://www.sangminkim.com/UBCKISS/category/news/jsonNews.php"];
NSData *jsonData = [NSData dataWithContentsOfURL:jsonURL];
NSError* error;
NSArray* json = [NSJSONSerialization
JSONObjectWithData:jsonData //1
options:kNilOptions
error:&error];
NSLog(#"First Dictionary: %#", [json objectAtIndex:0]);
//Log output:
// First Dictionary: {
// "news_date" = "2011-11-09";
// "news_id" = 5;
// "news_imageName" = "newsImage_111110_7633.jpg";
// "news_thread" = " \Uc774\Uc81c \Uc571 \Uac1c\Ubc1c \Uc2dc\Uc791\Ud574\Ub3c4 \Ub420\Uac70 \Uac19\Uc740\Ub370? ";
// "news_title" = "\Ub418\Ub294\Uac70 \Uac19\Uc9c0?";
// }
//Each item parsed is an NSDictionary
NSDictionary* item1 = [json objectAtIndex:0];
NSLog(#"Item1.news_date= %#", [item1 objectForKey:#"news_date"]);
//Log output: Item1.news_date= 2011-11-09
}

"Terminating app due to uncaught exception 'NSInvalidArgumentException'" error with stringByTrimmingCharactersInSet on iPhone

I am reading JSON data back from a server, and I am trying to parse a particular string that contains an HTML URL. The data is in an NSString called current_weatherIconUrl2. The console output from Xcode is below:
2010-07-06 17:17:46.628 WhatToDo[13437:20b] Current Condition: URL2:("http://www.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0001_sunny.png")
What I tried to do is use "stringByTrimmingCharactersInSet" to parse the '(', '"', and also the line feed and newlines, but I am instead getting the NSInvalidArgumentException:
2010-06-30 00:18:07.357 WhatToDo[7299:20b] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '* -[NSCFArray stringByTrimmingCharactersInSet:]: unrecognized selector sent to instance 0x3e84970'
Here is an extract of the data that is returned from the server (information I want to extract is bolded):
2010-07-06 17:17:46.627 WhatToDo[13437:20b] Results: {
data = {
"current_condition" = (
{
cloudcover = 75;
humidity = 42;
"observation_time" = "08:47 AM";
precipMM = "0.0";
pressure = 1003;
"temp_C" = 36;
"temp_F" = 97;
visibility = 10;
weatherCode = 113;
weatherDesc = (
{
value = Sunny;
}
);
**weatherIconUrl = (
{
value = "http://www.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0001_sunny.png";
}
);**
winddir16Point = WSW;
winddirDegree = 250;
windspeedKmph = 31;
windspeedMiles = 19;
}
);
};
}
Here is the code that parses the data into NSString variables.
- (void) readWeather {
NSLog(#"readWeather started");
NSMutableArray *imageArray = [[NSMutableArray alloc] init];
NSData *jsonObjectString;
NSString *completeString = [NSString stringWithFormat:
#"http://www.worldweatheronline.com/feed/weather.ashx?key=988ae47cc3062016100606&lat=25.04&lon=121.55&num_of_days=5&format=json", jsonObjectString];
NSLog(#"Weather URL: %#", completeString);
NSURL *urlForValidation = [NSURL URLWithString:completeString];
NSMutableURLRequest *validationRequest = [[NSMutableURLRequest alloc] initWithURL:urlForValidation];
[validationRequest setHTTPMethod:#"POST"];
NSData *responseData = [NSURLConnection sendSynchronousRequest:validationRequest returningResponse:nil error:nil];
[validationRequest release];
// Store incoming data into a string
NSString *jsonString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
// Create a dictionary from the JSON string
NSDictionary *results = [jsonString JSONValue];
NSLog(#"Results: %#", results);
NSArray *data = [[results objectForKey:#"data"] objectForKey:#"current_condition"];
NSArray *data2 = [[results objectForKey:#"data"] objectForKey:#"weather"];
NSCharacterSet *skipSet = [NSCharacterSet characterSetWithCharactersInString:#"("];
for (NSArray *current_condition in data)
{
// Get title of the image
NSString *temp_C = [current_condition valueForKey:#"temp_C"];
NSString *current_weatherDesc = [current_condition valueForKey:#"weatherDesc"];
NSString *current_weatherIconUrl = [current_condition valueForKey:#"weatherIconUrl"];
NSString *current_weatherIconUrl2= [current_weatherIconUrl valueForKey:#"value"];
//Commented out because this will create an exception:
//NSString *current_weatherIconUrl3 = [current_weatherIconUrl2 stringByTrimmingCharactersInSet:skipSet];
//NSLog(#"Current Condition: URL2: %#", *(current_weatherIconUrl3);
//Commented out because this will create an exception:
//current_weatherIconUrl3 = [current_weatherIconUrl3 stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}
Can someone tell me what I am doing wrong or if there is a better method than using stringByTrimmingCharactersInSet?
The error you're getting actually describes what goes wrong:
2010-06-30 00:18:07.357 WhatToDo[7299:20b] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '* -[NSCFArray stringByTrimmingCharactersInSet:]: unrecognized selector sent to instance 0x3e84970'
You're trying to send an unrecognized selector (stringByTrimmingCharactersInSet:) to an instance of NSCFArray (NSArray).
Obviously, this selector only exists on NSString, so this won't work.
It appears that [current_weatherIconUrl valueForKey:#"value"] really is an NSArray, not an NSString.
Thanks for your help Douwe M. I was able to make some modifications, and now the code creates the variables I need. See below...
NSArray *weatherIconUrl2= [weatherIconUrl valueForKey:#"value"];
NSString *weatherIconUrl3 = [[weatherIconUrl2 valueForKey:#"description"] componentsJoinedByString:#""];
[imageArray addObject:[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:weatherIconUrl3]]]];
-Todd
Your json response may not in a correct format.
So, please validate your JSON response on jsonlint