Getting Null values when accessing JSON data from Objective C - objective-c

I have the following JSON data trying to parse in Objective C - my code is returning nulls for the lower level object values - userid, FirstName and LastName
The complete JSON is:
{
"members" :
[
{"member" : {"userid":"1","FirstName":"ramesh","LastName":"babu"}},
{"member" : {"userid":"2","FirstName":"ramesh2","LastName":"babu2"}},
{"member" : {"userid":"3","FirstName":"ramesh3","LastName":"babu3"}}
]
}
My code is:
- (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* members = [json objectForKey:#"members"]; //2
NSString *text1 = [json description];
jsonSummary.text = text1;
NSEnumerator *e = [members objectEnumerator];
NSArray *keys = [NSArray arrayWithObjects:#"userid", #"FirstName", #"LastName", nil];
NSDictionary * member;
while (member = (NSDictionary *)[e nextObject]) {
// do something with object
// Iterate it
text1 = [member description];
NSLog(#"MEMBER ROW DATA%#", text1);
for (id key in keys) {
text1 = [member description];
NSLog(#"key: %# value:%# ", key, [member objectForKey:key]);
}
}
}
Any help would be appreciated!!

According to the sample JSON data, the "members" array contains dictionaries that each have a single key "member". The "member" key's value contains the dictionary with the lower level member data.
Your code assumes that the dictionaries with the lower level values are the array elements but they're not.
You need to first get to the "member" key value and then get the lower level values.
Changing this line:
NSLog(#"key: %# value:%# ", key, [member objectForKey:key]);
to:
NSLog(#"key: %# value:%# ", key,
[[member objectForKey:#"member"] objectForKey:key]);
should do it though I'd change the variable names a bit to make it less confusing.

Related

Filtering Parsed JSON in Objective-C

I'm trying to take out the "lasttradeprice" in https://www.allcrypt.com/api.php?method=singlemarketdata&marketid=672 but I can't seem to figure out how to grab the "lasttradeprice" piece.
How would I 'filter' the "price" out? None of the other information is relevant.
Current Code:
NSURL * url=[NSURL URLWithString:#"https://www.allcrypt.com/api.php?method=singlemarketdata&marketid=672"]; // pass your URL Here.
NSData * data=[NSData dataWithContentsOfURL:url];
NSError * error;
NSMutableDictionary * json = [NSJSONSerialization JSONObjectWithData:data options: NSJSONReadingMutableContainers error: &error];
NSLog(#"%#",json);
NSMutableArray * referanceArray=[[NSMutableArray alloc]init];
NSMutableArray * periodArray=[[NSMutableArray alloc]init];
NSArray * responseArr = json[#"lasttradeprice"];
for(NSDictionary * dict in responseArr)
{
[referanceArray addObject:[dict valueForKey:#"lasttradeprice"]];
[periodArray addObject:[dict valueForKey:#"lasttradeprice"]];
}
NSLog(#"%#",referanceArray);
NSLog(#"%#",periodArray);
NOTE: Keep in mind I've never worked with JSON before so please keep your answers dumbed down a tad.
Key value coding provides an easy way to dig through that data. Use the key path for the values you want. For example, it looks like you could get the array of recent trades using the path "return.markets.OMC.recenttrades" like this (assuming your code to get the json dictionary):
NSArray *trades = [json valueForKeyPath:#"return.markets.OMC.recenttrades"];
That's a lot more concise than having to dig down one level at a time.
The value returned for a given key by an array is the array of values returned by the array's members for that key. In other words, you can do this:
NSArray *recentprices = [trades valueForKey:#"price"];
And since that's just the next step in the key path, you can combine the two operations above into one:
NSArray *recentprices = [json valueforKeyPath:#"return.markets.OMC.recenttrades.price"];
The only down side here is that there's no real error checking -- either the data matches your expectations and you get back your array of prices, or it doesn't match at some level and you get nil. That's fine in some cases, not so much in others.
Putting that together with the relevant part of your code, we get:
NSURL *url = [NSURL URLWithString:#"https://www.allcrypt.com/api.php?method=singlemarketdata&marketid=672"];
NSData *data = [NSData dataWithContentsOfURL:url];
NSError *error = nil;
NSMutableDictionary *json = [NSJSONSerialization JSONObjectWithData:data options: NSJSONReadingMutableContainers error:&error];
NSArray *recentprices = [json valueforKeyPath:#"return.markets.OMC.recenttrades.price"];
Update: I just noticed that you want the "lasttradeprice", not the array of prices. Given that, the key path to use is simply #"return.markets.OMC.lasttradeprice", and the value you'll get back will be a string. So replace the last line above with:
NSString *lastTradePrice = [json valueforKeyPath:#"return.markets.OMC.lasttradeprice"];
The value you want is buried a few dictionaries deep. One general idea might be to dig recursively, something like this:
- (BOOL)isCollection:(id)object {
return [object isKindOfClass:[NSArray self]] || [object isKindOfClass:[NSDictionary self]];
}
- (void)valuesForDeepKey:(id)key in:(id)collection results:(NSMutableArray *)results {
if ([collection isKindOfClass:[NSDictionary self]]) {
NSDictionary *dictionary = (NSDictionary *)collection;
if (dictionary[key]) [results addObject:dictionary[key]];
for (id deeperKey in [dictionary allKeys]) {
if ([self isCollection:dictionary[deeperKey]]) {
[self valuesForDeepKey:key in:dictionary[deeperKey] results:results];
}
}
} else if ([collection isKindOfClass:[NSArray self]]) {
NSArray *array = (NSArray *)collection;
for (id object in array) {
if ([self isCollection:object]) {
[self valuesForDeepKey:key in:object results:results];
}
}
}
}
Then call it like this:
NSMutableArray *a = [NSMutableArray array];
[self valuesForDeepKey:#"lasttradeprice" in:json results:a];
NSLog(#"%#", a);

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:.

Strange NSData Output

I have some unexpected results coming from the following code:
- (NSData *)postDataWithDict:(NSDictionary *)postDict
{
// Assume key is urlValid
NSUInteger postCount = [postDict count];
NSMutableArray *buildArray = [[NSMutableArray alloc] initWithCapacity:postCount];
for (NSString *key in postDict) {
//post data is key=value&key=value&key=value...
// start with key
NSMutableString *arrayLine = [NSMutableString stringWithString:key];
[arrayLine appendString:#"="];
// analyze and then append value
id postValue = [postDict objectForKey:key];
if ([postValue isKindOfClass:[NSNumber class]]) {
NSString *valueString = [NSString stringWithFormat:#"%#",postValue];
[arrayLine appendString:valueString];
}
else if ([postValue isKindOfClass:[NSString class]]) {
NSString *urlEncodedString = [self urlEncodeValue:postValue];
[arrayLine appendString:urlEncodedString];
}
else {
NSLog(#"postKey: %#, postValue class:%#", key, [postValue class]);
NSError *jsonError = nil;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:postValue
options:0
error:&jsonError];
if (jsonError != nil) {
NSLog(#"JSON serialization failed: %# - %#", [jsonError localizedDescription], [jsonError userInfo]);
NSLog(#"value: %#", postValue);
}
else {
// need to urlencode
NSString *stringifyJSON = [NSString stringWithUTF8String:[jsonData bytes]];
NSString *urlJSONstring = [self urlEncodeValue:stringifyJSON];
[arrayLine appendString:urlJSONstring];
}
}
[buildArray addObject:arrayLine];
}
NSString *postString = [buildArray componentsJoinedByString:#"&"];
NSData *postData = [postString dataUsingEncoding:NSUTF8StringEncoding];
//testing
NSLog(#"Post Dict: %#", postDict);
NSLog(#"Post Array: %#", buildArray);
NSLog(#"Post String: %#", postString);
NSLog(#"Post Data: %#", [NSString stringWithUTF8String:[postData bytes]]);
return postData;
}
My //testing log results:
Post Dict: {
authenticationString = b3210c0bc6d2c47f4c2f7eeea12e063d;
dataMode = updateSingle;
dateCreated = "374300293.81108";
dateModified = "374609294.313093";
dateSynced = "374610683.588062";
entityName = CommodityTypes;
myName = 21;
sortKey = 21;
username = iPhoneAdamek;
usernameString = iPhoneAdamek;
uuidKey = "53403EAE-DD4F-4226-A979-316EF7F43991";
}
Post Dict looks good. Just what I wanted.
2012-11-14 13:31:23.640 FoodyU[11393:907] Post Array: (
"myName=21",
"dataMode=updateSingle",
"dateSynced=374610683.588062",
"uuidKey=53403EAE-DD4F-4226-A979-316EF7F43991",
"sortKey=21",
"dateModified=374609294.313093",
"entityName=CommodityTypes",
"dateCreated=374300293.81108",
"authenticationString=b3210c0bc6d2c47f4c2f7eeea12e063d",
"usernameString=iPhoneAdamek",
"username=iPhoneAdamek"
)
Post Array looks good. Strings are all set to be concatenated for a HTTP POST string.
2012-11-14 13:31:23.641 FoodyU[11393:907] Post String: myName=21&dataMode=updateSingle&dateSynced=374610683.588062&uuidKey=53403EAE-DD4F-4226-A979-316EF7F43991&sortKey=21&dateModified=374609294.313093&entityName=CommodityTypes&dateCreated=374300293.81108&authenticationString=b3210c0bc6d2c47f4c2f7eeea12e063d&usernameString=iPhoneAdamek&username=iPhoneAdamek
Post String looks good. I'm ready to convert it to data to use in [NSMutableURLRequest setHTTPBody:postData].
2012-11-14 13:31:23.643 FoodyU[11393:907] Post Data: myName=21&dataMode=updateSingle&dateSynced=374610683.588062&uuidKey=53403EAE-DD4F-4226-A979-316EF7F43991&sortKey=21&dateModified=374609294.313093&entityName=CommodityTypes&dateCreated=374300293.81108&authenticationString=b3210c0bc6d2c47f4c2f7eeea12e063d&usernameString=iPhoneAdamek&username=iPhoneAdamekoneAdamek;
usernameString = iPhoneAdamek;
uuidKey = "53403EAE-DD4F-4226-A
WTF??? How did &username=iPhoneAdamek become &username=iPhoneAdamekoneAdamek;
usernameString = iPhoneAdamek;
uuidKey = "53403EAE-DD4F-4226-A?
I'm fairly new to Cocoa. Is there something wrong with:
NSData *postData = [postString dataUsingEncoding:NSUTF8StringEncoding];
or
NSLog(#"Post Data: %#", [NSString stringWithUTF8String:[postData bytes]]);
You shouldn't be using NSLog of NSData as,
NSLog(#"Post Data: %#", [NSString stringWithUTF8String:[postData bytes]]);
Instead use it as,
NSLog(#"Post Data: %#", [[NSString alloc] initWithData:postData encoding:NSUTF8StringEncoding]);
[NSString stringWithUTF8String:[postData bytes]] always returns unexpected results.
As per documentation for bytes,
bytes: Returns a pointer to the receiver’s contents.
And as per Apple documentation for stringWithUTF8String,
stringWithUTF8String:
Returns a string created by copying the data from a given C array of UTF8-encoded bytes.
Parameters: bytes - A NULL-terminated C array of bytes in UTF8 encoding.
So when you are using [postData bytes], it is not NULL-terminated and hence when you are using with stringWithUTF8String returns the data written in memory till it encounters a NULL-termination.

Importing JSON objects into NSArray

Trying to parse this JSON object in objective-C and creating an NSArray with these objects.
The first value is a counter and is specific for the object. All other values are unique.
{ "myData": [
["1","1","110","dollar","8.0","2.8","0.1","11.6"],
["2","1","110","euro","4.0","3.2","1.5","4.4"],
["3","1","120","rupier","6.0","2.9","1.3","10.8"],
["4","1","120","dinero","4.0","3.3","1.5","4.4"],
["5","2","130","drahmer","8.0","2.9","1.3","11.2"],
] }
Tried this code:
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:myData
options:kNilOptions
error:&error];
NSArray *currencyInformation = [json objectForKey:#"myData"];
But the objects are not there. Though the count of the array is 5.
Each object in the array is an array itself, so:
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:myData
options:kNilOptions
error:&error];
NSArray *currencyInformation = [json objectForKey:#"myData"];
for (NSArray *info in currencyInformation) {
// Then access each "column" with [info objectAtIndex:0,1,2,3,...]
}
In this data structure you would need to access things by index e.g
for (NSArray *currency in currencyInformation) {
NSLog(#"Currency: %#", [currency objectAtIndex:3]);
}
If you want to access things by key then you would need to change your JSON to use an array of objects instead of an array of arrays. Something like this:
{
"myData": [
{
"primaryKey" : 1,
"currency" : "dollar",
<other keys + values>...
},
]
}
In which case you could now do something like:
for (NSDictionary *currency in currencyInformation) {
NSLog(#"Currency: %#", [currency valueForKey:#"currency"]);
}

How to return arrays object + count IOS

hi at all ,I've this code :
+(NSArray *)splatterUrls
{
NSString *jsonString = [ ApiMethod jsonOfStores];
NSDictionary *results =[jsonString objectFromJSONString];
NSArray *movieArray = [results objectForKey:#"Seasons"];
//int i=0;
// Search for year to match
for (NSDictionary *movie in movieArray)
{
NSNumber *idSplatterMovie = [movie objectForKey:#"Id"];
// NSLog(#" %#", idSplatterMovie );
NSArray *try = [movie objectForKey:#"Episodes"];
// NSLog(#"%#", try);
for (NSDictionary *op in try)
{
if([idSplatterMovie integerValue] == 46)
{
//i++;
NSArray *movieArrayString = [op objectForKey:#"Url"];
// NSLog(#" %#", movieArrayString);
return movieArrayString;
}
}
}
}
I want to return movieArrayString with all his objects and how many object contains in it. I think that I should use this method : + (id)arrayWithObjects:(const id *)objects count:(NSUInteger)count. It's possible? If yes, can you tell me how can use it?
Thank you so much!
by the way , i have to call splatterUrls method and implement in home.m that it is :
- (void)viewDidLoad
{
[super viewDidLoad];
NSArray *urlSplatter= [GetSplatterUrlsMovie splatterUrls];
NSLog(#" %#", urlSplatter);
}
Looks good as it is to me.
Do this to return your movies array, array will be equal to your movies array:
NSArray *array = [self splatterUrls];
Then to get the count/number of objects in your array do this, i is equal to the number of objects in the array:
int i = [array count];
What is the problem ??
You return a NSarray ... call the method count on your NSarray object!