This has got to be something obvious that I am doing wrong. I have been banging my head against a wall trying to figure out what is going on. I already have this json parsing done in the android version of my app, now trying to parse this simple json in xcode and can't get it done.
NSError *myError = nil;
NSDictionary *res = [NSJSONSerialization JSONObjectWithData:self.responseData options:kNilOptions error:&myError];
NSLog([res objectForKey:#"Date"]);
This code get me the "unrecognized selector sent to instance" error.
Here is the json data and you can see Date is one of the objects:
[{"Date":"2016-06-17T22:56:33.0811255-05:00"}]
Thanks in advance for any help on this issue. I've tried to simplify this post, but if more info is needed I will try and quickly provide.
http://i.stack.imgur.com/Y5fsT.png
JSONObjectWithData is returning an array of dictionaries and not a dictionary. Your print out of the raw JSON confirms this:
[{"Date":"2016-06-17T22:56:33.0811255-05:00"}] // This is an array
However you're attempting to treat that response object like a dictionary. In doing so you're calling a dictionary method (objectForKey:) on an array. This results in a crash. Try something like this:
NSError *error = nil;
id responseObject = [NSJSONSerialization JSONObjectWithData:self.responseData options:kNilOptions error:&error];
if (error)
{
// Handle error
return;
}
NSLog(#"%#", responseObject);
if ([responseObject isKindOfClass:[NSArray class]])
{
NSArray *responseArray = (NSArray *)responseObject;
for (id item in responseArray)
{
NSLog(#"%#", item);
if ([item isKindOfClass:[NSDictionary class]])
{
NSDictionary *dictionary = (NSDictionary *)item;
NSString *dateString = [dictionary objectForKey:#"Date"];
NSLog(#"%#", dateString);
}
}
}
else
{
// responseObject is not an array...
}
I'm pretty sure this is because you should first set res as [NSDictionary]. Then pick the first element in that array and then get objectForKey: "Date". Normal JSON Data starts with a {, this starts with a [. Which means it's an array.
You can see it for yourself in the screenshot when it says #: 1 Element . THEN it says 1 key/value pair. The NSDictionary is inside an array.NSError
Try this code:
*myError = nil;
[NSDictionary] *res = [NSJSONSerialization JSONObjectWithData:self.responseData options:kNilOptions error:&myError];
if (res.count > 0) {
NSLog([res[0] objectForKey:#"Date"]);
}
Related
I have an NSArray that looks like this
NSDictionary *dataDict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
NSLog(#"main: %#", [dataDict valueForKey:#"main"]);
main: [{"city": "dallas", "description": "this is my test description"}]
And I am trying to turn it into a NSDictionary so I get get element like [mainDict objectForKey#"city"]
So I tried this
NSLog(#"%#", [[mainArray objectAtIndex:0] objectForKey:#"city"]);
Thinking it would get the first element in mainArray and then the object that I want but I keep getting this error
[__NSCFString objectAtIndex:]: unrecognized selector sent to instance
How can I make the NSAarry into a NSDictionary?
Thanks
Create a for loop for list when you get response in [{},{}] format that means its a list of elements . Or you can ask your API developer to correct the error .
Any ways simple solution here is :
for (NSDictionary *d in [dataDict valueForKey:#"main"]){
NSlog (#"%#",d);
NSlog (#"%#",[d objectForKey :#"city"]);
}
Your error is saying mainarray is not a NSArray, it is NSString. So please check like this
NSDictionary *dataDict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
NSLog(#"main: %#", [dataDict valueForKey:#"main"]);
if ([[dataDict valueForKey:#"main"] isKindOfClass:[NSArray class]]) {
NSArray *mainArray = [dataDict valueForKey:#"main"];
NSLog(#"City == %#",[[mainArray objectAtIndex:0] objectForKey:#"city"]);
}else{
NSLog(#"mainarray is kind of -> %#", NSClassFromString([dataDict valueForKey:#"main"]));
}
NSArray *mainArray = #[#{#"city":#"dallas", #"description":#"this is my test description"}];
NSLog(#"%#", [[mainArray objectAtIndex:0] objectForKey:#"city"]);
no problem ....
Thank you reading my post, I known this topic was asked so many time, and I had saw that but no luck...
I want to parse a simple JSON string, as followings:
[
{
"id":"1",
"name_en":"Photography",
"subchannels":[
{
"id":"4",
"name_en":"John"
},
{
"id":"18",
"name_en":"Sam"
}
]
},
{
"id":"7",
"name_en":"Equipment",
"subchannels":[
{
"id":"25",
"name_en":"ABC Company"
},
{
"id":"40",
"name_en":"CDE Company"
}
]
}
]
It had convert this string to NSDictionary
NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *testDic = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&e];
Then I list the Dictionary Key
for(id key in testDic) {
NSLog(#"%#", key);
}
The result is the entire record as the Dictionary Key, so I can't use [testDic objectForKey:key] to retrieve the value.
How can I get the first row name_en and the second row subchannels value?
(is it possible to retrieve easily like xpath in XML?)
Thank you for helping.
First of all. The root object of your model is NSArray object - not `NSDictionary. '[]' means array and {} means dictionary.
NSArray *dataArray = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&e];
for (NSDictionary *entry in dataArray) {
NSString *name = entry[#"name_en"];
NSArray *subchannels = entry[#"subchannels"]; //array of dictionaries
NSLog(#"Name %s", name);
for (NSDictionary *subchannel in subchannels) {
NSLog(#"Subchannels name %# id: %d", subchannel[#"name"], [subchannel[#"id"] integerValue]);
}
}
If you want to perform advances JSON parsing I encourage you to look at Mantle github project.
I'm trying to get the data from a JSON response object in my iOS app after I log in. I keep getting this error though.
Error:
'NSInvalidArgumentException', reason: '-[__NSCFArray objectForKeyedSubscript:]: unrecognized selector sent to instance 0x8fc29b0'
Here is my code for the request, I'm using AFNetworking:
self.operation = [manager GET:urlString parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSDictionary *JSON = (NSDictionary *)responseObject;
NSDictionary *user = JSON[#"user"];
NSString *token = user[#"auth_token"];
NSString *userID = user[#"id"];
// NSString *avatarURL = user[#"avatar_url"];
// weakSelf.credentialStore.avatarURL = avatarURL;
weakSelf.credentialStore.authToken = token;
weakSelf.credentialStore.userId = userID;
weakSelf.credentialStore.username = self.usernameField.text;
weakSelf.credentialStore.password = self.passwordField.text;
[SVProgressHUD dismiss];
[self dismissViewControllerAnimated:YES completion:nil];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
if (operation.isCancelled) {
return;
}
[SVProgressHUD showErrorWithStatus:#"Login Failed"];
NSLog(#"%#", error);
}];
What the JSON response object looks like logged:
<__NSCFArray 0x8cac0b0>(
{
user = {
"auth_token" = b3a18e0fb278739649a23f0ae325fee1e29fe5d6;
email = "jack#jack.com";
id = 1;
username = jack;
};
}
)
I'm converting the array to a Dictionary using pointers like this:
EDIT: As pointed out in the comments incase anyone else stumbles across this with limited knowledge in iOS. I'm casting here not converting. See the answers for a full explanation.
NSDictionary *JSON = (NSDictionary *)responseObject;
I'm new to iOS, apologies if problem is obvious.
Thanks for any help.
The "conversion" you do is not doing any conversion, it's a cast. This simply tells the compiler to ignore the type it knows for this object and act as if it's the type you pass it.
Looking at the output you have, you don't get a dictionary back, but an array of dictionaries with a single dictionary. To get to the first dictionary you can use this instead of the cast:
NSDictionary *JSON = [responseObject objectAtIndex:0];
Note that since you get your data from a web service, you should probably also check if the contents you get are what you expect.
You say:
I'm converting the array to a Dictionary using pointers like this:
But that is not what you are doing. You are casting it, but the underlying object is still an array.
From the JSON response you can see that those JSON is constructed as an array with a single element which is a dictionary. You can get to the dictionary by calling [responseObject firstObject];. Of course, so that you don't get error going in the other direction, you should check how the input is constructed before calling any array or dictionary specific methods on the response object.
You have to convert your self but do not use casting.
Or, this is the code to detect if a json object is an array or dictionary
NSError *jsonError = nil;
id jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:&jsonError];
if ([jsonObject isKindOfClass:[NSArray class]]) {
NSLog(#"its an array!");
NSArray *jsonArray = (NSArray *)jsonObject;
NSLog(#"jsonArray - %#",jsonArray);
}
else {
NSLog(#"its probably a dictionary");
NSDictionary *jsonDictionary = (NSDictionary *)jsonObject;
NSLog(#"jsonDictionary - %#",jsonDictionary);
}
I am trying to parse a JSON dictionary in the form of:
{
"bible": {
"book": [
{
"bookName": "Genesis",
"chapter": [
{
"chapterNum": "1",
"verse": [
{
"verse": "In the beginning God created the heaven and the earth.",
"verseNum": "1"
},
{
"verse": "And the earth was without form, and void; and darkness was upon the face of the deep. And the Spirit of God moved upon the face of the waters.",
"verseNum": "2"
},
I am having difficulties getting to the proper data within this structure. My goal is to create a Verse managed object that has a verseNum, verse (the text), chapterNum, and bookName properties.
I need help creating the object. Currently, when I create the NSDictionary using NSJSONSerialization, I only obtain one dictionary, with a single NSCFString:
NSError* err = nil;
NSString* dataPath = [[NSBundle mainBundle] pathForResource:#"kjv"
ofType:#"json"];
NSDictionary *bible = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:dataPath]
options:kNilOptions
error:&err];
for (NSDictionary *book in [bible valueForKey:#"bible"]) {
NSLog(#"%#", book);
}
The console output simply reads: book
Try the following code:
NSError *error = nil;
id JSONResponse = [NSJSONSerialization JSONObjectWithData:self.responseData
options:0
error:&error];
if (error) {
NSLog(#"JSON Error: %#", error);
return;
}
// Should be an NSDictionary or NSArray
NSLog(#"JSON response: %#", [JSONResponse description]);
NSArray *books = [JSONResponse valueForKeyPath:#"bible.book"];
for (NSDictionary *book in books) {
NSLog(#"%#", book);
NSString *bookName = [book valueForKey:#"bookName"];
NSArray *chapters = [book valueForKey:#"chapter"];
// loop through the chapters
...
NSArray *verses = [book valueForKey:#"verse"];
// loop through the verses
...
}
Seems your JSON document is an object (dictionary), containing one element named "bible". bible is itself a dictionary containing one element named "book". book is an array. The array elements are objects, with an item "bookName" containing a string, and another item "chapter" containing an array and so on. So:
NSDictionary* JSONResponse = ...
NSAssert ([JSONResponse isKindOfClass:[NSDictionary class]]);
NSDictionary* bible = JSONResponse [#"bible"];
NSAssert ([bible isKindOfClass:[NSDictionary class]]);
NSArray* books = bible [#"book"];
NSAssert ([books isKindOfClass:[NSArray class]]);
for (NSDictionary* book in books)
{
NSAssert ([book isKindOfClass:[NSDictionary class]]);
NSString* bookName = book [#"bookName"];
NSArray* chapters = book [#"chapter"];
}
and so on.
i need to parse the Apple JSON but i have a little problem. I'm now doing this:
The problem is here:
- (void)fetchedData:(NSData *)responseData {
NSError* error;
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:responseData
options:kNilOptions
error:&error];
NSNumber *resultCount = [json objectForKey:#"resultCount"];
NSLog(#"%i", [resultCount intValue]);
NSArray * AppStoreUrlParse = [json objectForKey:#"results"];
NSDictionary* StoreParse = [AppStoreUrlParse objectAtIndex:0];
NSLog(#"%#", [json objectForKey:#"price"]);
}
On this line:
NSLog(#"%i", [resultCount intValue]);
The NSlog is returing: 1 like in the JSON ( http://itunes.apple.com/lookup?id=387633954)
But on this line
NSLog(#"%#", [json objectForKey:#"price"]);
The NSLOG returns (Null)
does anyone know how i can get the price from the json?
It seems that 'price' is part of a dictionary that is the first item in the 'results' array.
Can you try
NSLog(#"%#", [[AppStoreUrlParse objectAtIndex:0] objectForKey:#"price"]);
This would get the value of the key 'price' in the first element of the 'results' array of your JSON.
EDIT
Actually, rereading your code, you are already getting the first element of the array in this line:
NSDictionary* StoreParse = [AppStoreUrlParse objectAtIndex:0];
So all you need to do is change json by StoreParse in your NSLog:
NSLog(#"%#", [StoreParse objectForKey:#"price"]);