I have the following iteration:
historialServicios = [[NSMutableDictionary alloc]init];
// Parse and loop through the JSON
for (dictionary in messageArray) {
//datos de nivel objects
NSString * code = [dictionary objectForKey:#"code"];
NSString * date = [dictionary objectForKey:#"date"];
//datos de nivel client
NSDictionary *level2Dict = [dictionary objectForKey:#"client"];
id someObject = [level2Dict objectForKey:#"email"];
NSLog(#"NOMBRE===%#",someObject);
NSString * email = someObject;
NSLog(#"EMAIL=%#",email);
NSLog(#"CODE=%#",code);
NSLog(#"DATE=%#",date);
//insertamos objetos en diccionario historialServicios
}
The iteration is looping inside the root node of a json tree and also inside a child node "client".
What I need is to create a NSMutableArray of dictionaries. Each dictionary has to include the retrieved objects from each iteration, in this case the keys are code, data and email. Code and data from the root node, and email from the child node.
Following the example, each dictionary should be an object with the keys and values:
KEYS VALUES
code NSString code
date NSString date
email NSString email
How can I perform this way to create the NSMutableArray?
Try:
historialServicios = [[NSMutableDictionary alloc]init];
array = [NSMutableArray new];
// Parse and loop through the JSON
for (dictionary in messageArray) {
//datos de nivel objects
NSString * code = [dictionary objectForKey:#"code"];
NSString * date = [dictionary objectForKey:#"date"];
//datos de nivel client
NSDictionary *level2Dict = [dictionary objectForKey:#"client"];
id someObject = [level2Dict objectForKey:#"email"];
// ADDING TO ARRAY
[array addObject:#{#"code": code, #"date": date, #"email":someObject}];
NSLog(#"NOMBRE===%#",someObject);
NSString * email = someObject;
NSLog(#"EMAIL=%#",email);
NSLog(#"CODE=%#",code);
NSLog(#"DATE=%#",date);
//insertamos objetos en diccionario historialServicios
}
Related
this is my json content.
[
{
"sha":"30eae8a47d0203ac81699d8fc2ab2632de2d0bba",
"commit":{
"author":{
"name":"Madhura Bhave",
"email":"mbhave#pivotal.io",
"date":"2017-03-23T23:14:32Z"
},
"committer":{
"name":"Madhura Bhave",
"email":"mbhave#pivotal.io",
"date":"2017-03-23T23:14:32Z"
},
"message":"Merge branch '1.5.x'",
}
}
]
and this is my main.i just want to retrieve key value from message and name,email,date from committer dictionary.i got stuck how to do that.
NSMutableArray *CommitArray = [[NSMutableArray alloc] init];
for (NSDictionary *CommitDictionary in CommitJson) {
CommitDict *commitDictObj = [[CommitDict alloc] init];
commitDictObj.message = [CommitDictionary objectForKey:#"message"];
for (NSDictionary *CommitterDictionary in [CommitDictionary objectForKey:#"committer"]) {
Committer *author = [[Committer alloc] init];
author.name = [CommitterDictionary objectForKey:#"name"];
author.email = [CommitterDictionary objectForKey:#"email"];
author.date = [CommitterDictionary objectForKey:#"date"];
}
[CommitArray addObject:commitDictObj];
}
for (int i =0 ; i < [CommitArray count] ; i++){
CommitDict *commitDictObj = [CommitArray objectAtIndex:i];
NSLog(#"Commit Message: %#", commitDictObj.message);
}
return 0;
}
}
i try fetch the json and display it value of message,name,email and date.how can i log the value of message, name, email and date?
Your array contains a dictionary, and that dictionary contains the commit dictionary, not the commit dictionary directly. Replace that part of your code:
for (NSDictionary *CommitDictionary in CommitJson) {
CommitDict *commitDictObj = [[CommitDict alloc] init];
With that:
for (NSDictionary *shaCommitDictionary in CommitJson) {
CommitDict *commitDictObj = [[CommitDict alloc] init];
NSDictionary *CommitDictionary = [shaCommitDictionary objectForKey:#"commit"];
(1) Convert JSON to NSDictionary
NSData *jsonData= ... // Assume you got the data already loaded
NSError *error = nil;
NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
(2) Access the dictionary values (fast enumeration available by now!!
NSString *message = dictionary[#"message"];
NSDictionary *author = dictionary[#"author"];
NSString *name = author[#"author"];
NSString *email = author[#"author"];
NSString *date = author[#"author"];
// OR:
// NSString *name = dictionary[#"author"][#"author"];
// NSString *email = dictionary[#"author"][#"author"];
// NSString *date = dictionary[#"author"][#"author"];
And thats it. I think the tricky thing is to get the JSON Data to the NSDictionary?
See here: https://stackoverflow.com/a/30561781/464016
NSDictionary *myDict = #{#"one":#"1",#"two":#"2"};
for (NSDictionary* tmp in myDict) {
NSLog(#"%#",tmp);
}
resut:
my tmpis NSString
I want to get a dictionary with key= one , value = 1
for in for NSDictionary will iterate the keys.
for (NSString * key in myDict) {
NSLog(#"%#",key);
NSString * value = [myDict objectForKey:key];
}
If you want to get a dictionary. You have to create a dictionary from these values
for (NSString * key in myDict) {
NSLog(#"%#",key);
NSString * value = [myDict objectForKey:key];
NSDictionary * dict = #{key:value};
}
Or you should init like this:
NSArray *arrDict = #[{#{"one":#"1"},#{#"two":#"2"}];
for (NSDictionary* tmp in arrDict) {
NSLog(#"%#",tmp);
}
You can get all keys from your dic then add the key and value to your new dic like this:
NSDictionary *myDict = #{#"one":#"1",#"two":#"2"};
NSArray *keys = [myDict allKeys];
for (NSString *key in keys) {
NSDictionary *yourDic = #{key: [myDict valueForKey:key]};
NSLog(#"%#", yourDic);
}
You didn't create it that way. If you wanted to have a NSDictionary inside another NSDictionary you should write something like this :
NSDictionary *myDict = #{
#"firstDict" : #{
#"one":#"1"
},
#"secondDict": #{
#"two":#"2"
}
};
Above code will create a NSDictionary with two dictionaries at keys #firstDict and #secondDict.
Also, bear in mind, that because dictionaries are key-value pairs, using a for-in loop, actually loops through the keys in that dictionary. So your code is equivalent to:
for(NSString *key in dict.allKeys) { ... }
I got the solution
NSDictionary *myDict = #{#"one":#"1",#"two":#"2"};
NSMutableArray *arrayObject = [[NSMutableArray alloc]init];
NSMutableArray *arrayKey = [[NSMutableArray alloc]init];
NSMutableArray *arrayObjectKey = [[NSMutableArray alloc]init];
NSMutableDictionary *dict = [[NSMutableDictionary alloc]init];
for (NSString *stringValue in myDict.allValues)
{
[arrayObject addObject:stringValue];
}
for (NSString *stringKey in myDict.allKeys)
{
[arrayKey addObject:stringKey];
}
for(int i = 0;i<[arrayKey count];i++)
{
dict = [[NSMutableDictionary alloc]initWithObjectsAndKeys:[NSString stringWithFormat:#"%#",[arrayKey objectAtIndex:i]],#"key",nil];
[dict setObject:[NSString stringWithFormat:#"%#",[arrayObject objectAtIndex:i]] forKey:#"value"];
[arrayObjectKey addObject:dict];
}
NSLog(#"The arrayObjectKey is - %#",arrayObjectKey);
The Output is
The arrayObjectKey is -
(
{
key = one;
value = 1;
},
{
key = two;
value = 2;
}
)
Create the dictionary:
NSDictionary *myDict = [NSDictionary dictionaryWithObjectsAndKeys:#"1",#"One",#"2","Two",nil];
Get a value out using:(this example tmp will be 1)
NSString *tmp = [myDict objectForKey:#"One"];
Display the output in console:
NSLog(#"%#",tmp);
To display the whole NSDictionary
NSLog (#"contents of myDict: %#",myDict);
What you are doing is creating a dictionary with key-value pairs. I think what you want to do is have an array with dictionaries.
NSArray *myArray = #[#{#"one":#"1"}, #{#"two":#"2"}];
for (NSDictionary* tmp in myArray) {
NSLog(#"%#",tmp);
}
However I don't see a point in doing this. What you could do is:
NSDictionary *myDict = #{#"one":#"1",#"two":#"2"};
for (NSString* key in [myDict allKeys]) {
NSLog(#"%# = %#", key, myDict[key]);
}
I am receiving a JSON string that I need to iterate to retrieve some objects values.
This is the structure
-meta
-objects
|_cabdriver
|_employee
|client
There are objects under the objects tree and there are also child nodes, like cabdriver and client. The child node cabdriver has also another child node called employee.
This is the way I am iterating it:
NSArray *messageArray = [json objectForKey:#"objects"];
historialServicios = [[NSMutableArray alloc]init];
// Parse and loop through the JSON
for (dictionary in messageArray) {
//datos de nivel objects
NSString * date = [dictionary objectForKey:#"date"];
NSString * origin = [dictionary objectForKey:#"origin"];
NSString * destiny = [dictionary objectForKey:#"destiny"];
NSString * rate = [dictionary objectForKey:#"service_rate"];
NSString * state = [dictionary objectForKey:#"state"];
NSString * time_service = [dictionary objectForKey:#"time_service"];
NSString * id_service = [dictionary objectForKey:#"id"];
//datos de nivel cliente
NSDictionary *level2Dict = [dictionary objectForKey:#"client"];
NSString *client_id = [level2Dict objectForKey:#"id"];
//datos de nivel cabdriver
NSDictionary *cabdriverLevelDict=[dictionary objectForKey:#"cabdriver"];
//datos de nivel employee
NSDictionary *employeeLevelDict = [cabdriverLevelDict objectForKey:#"employee"];
//datos del employee
NSString *driverName = [employeeLevelDict objectForKey:#"name"];
NSString *driverLastname = [employeeLevelDict objectForKey:#"lastname"];
NSString *driverPhone = [employeeLevelDict objectForKey:#"phone"];
NSString *driverId = [employeeLevelDict objectForKey:#"id"];
[historialServicios addObject:#{
#"time_service": time_service,
#"id_service": id_service,
#"rate": rate,
#"destiny": destiny,
#"state": state,
#"origin": origin,
#"client_id":client_id,
#"date": date,
#"driverName":driverName,
#"driverLastname": driverLastname,
#"driverPhone": driverPhone,
#"driverId": driverId
}];
NSLog(#"DESPUES DE ANADIR OBJETOS");
NSLog(#"OBJETO ANADIDO==>TIME SERVICE = %#, ID SERVICE=%#, SERVICE RATE=%#,SERVICE DATE=%#,DESTINY=%#, STATE =%#,CLIENT ID=%#, ORIGIN=%#,DRIVER NAME=%#, DRIVER LASTNAME=%#,DRIVER PHONE=%#, DRIVER ID=%#",time_service,id_service,rate,date,destiny,state,client_id,origin,driverName,driverLastname,driverPhone,driverId);
//insertamos objetos en diccionario historialServicios
}
Everything works fine if the object has all nodes but some times, the node cabdriver is empty and doesn't have the employee child node. If it is the case I get an exception is thrown and the app crashes.
How can I determined if the node employee doesn't exist and avoid to get the exception?
Thank you.
You could declare a category to deal with the [NSNull null] values that are injected into your json.
#interface NSDictionary (NilNull)
- (id)optionalObjectForKey:(id)key;
- (id)optionalObjectForKey:(id)key defaultValue:(id)defaultValue;
#end
#implementation NSDictionary (NilNull)
- (id)optionalObjectForKey:(id)key {
return [self optionalObjectForKey:key defaultValue:nil];
]
- (id)optionalObjectForKey:(id)key defaultValue:(id)defaultValue {
id obj = [self objectForKey:key];
return (obj == [NSNull null] || !obj) ? defaultValue : obj;
}
#end
Then use that instead:
NSDictionary *cabdriverLevelDict = [dictionary optionalObjectForKey:#"cabdriver"];
NSDictionary *employeeLevelDict = [cabdriverLevelDict optionalObjectForKey:#"employee"];
You haven't posted the contents of your exception, but from the looks of it, it's probably related to trying to add nil values to your new dictionary.
Then use a default value of [NSNull null] for all your data lookups that produce objects with which you will construct your final dictionary. The full lookup source will now be like this:
NSString * date = [dictionary optionalObjectForKey:#"date" defaultValue:[NSNull null]];
NSString * origin = [dictionary optionalObjectForKey:#"origin" defaultValue:[NSNull null]];
NSString * destiny = [dictionary optionalObjectForKey:#"destiny" defaultValue:[NSNull null]];
NSString * rate = [dictionary optionalObjectForKey:#"service_rate" defaultValue:[NSNull null]];
NSString * state = [dictionary optionalObjectForKey:#"state" defaultValue:[NSNull null]];
NSString * time_service = [dictionary optionalObjectForKey:#"time_service" defaultValue:[NSNull null]];
NSString * id_service = [dictionary optionalObjectForKey:#"id" defaultValue:[NSNull null]];
//datos de nivel cliente
NSDictionary *level2Dict = [dictionary optionalObjectForKey:#"client" defaultValue:[NSDictionary dictionary]];
NSString *client_id = [level2Dict optionalObjectForKey:#"id" defaultValue:[NSNull null]];
//datos de nivel cabdriver
NSDictionary *cabdriverLevelDict=[dictionary optionalObjectForKey:#"cabdriver" defaultValue:[NSDictionary dictionary]];
//datos de nivel employee
NSDictionary *employeeLevelDict = [cabdriverLevelDict optionalObjectForKey:#"employee" defaultValue:[NSDictionary dictionary]];
//datos del employee
NSString *driverName = [employeeLevelDict optionalObjectForKey:#"name" defaultValue:[NSNull null]];
NSString *driverLastname = [employeeLevelDict optionalObjectForKey:#"lastname" defaultValue:[NSNull null]];
NSString *driverPhone = [employeeLevelDict optionalObjectForKey:#"phone" defaultValue:[NSNull null]];
NSString *driverId = [employeeLevelDict optionalObjectForKey:#"id" defaultValue:[NSNull null]];
Try this here:
if( cabdriverLevelDict.allkeys.count ){
// Do something with the dict
} else {
// dict is empty
}
Basically, you need to check every single result that you get. If you don't do that, your app is open to attacks, and one attack might allow a hacker into the user's device and cause unlimited damage. Where you expect a dictionary, you might get nil, you might get a null, you might get a number, or a string, just anything. It's quite simple.
NSDictionary* dict = ...;
if (! [dict isKindOfClass:[NSDictionary class]]) dict = nil;
In Objective-C, nil objects are quite safe. You can use objectForKey [#"employee"], for example, and all that will happen is that you get nil as the result. And you could have received nil anyway.
There is no point checking for [NSNull null] only, because any other result that the server gave you will crash your app just the same. Just check for what you actually expect. Throwing away incorrect data is fine, after all the JSON deserialiser will throw away everything if just a single byte of data is wrong.
Sometimes you need to do a bit more care because servers misbehave and you have to cope with it. For example, a server supposed to return an array of dictionaries might give you just a dictionary if there is only one, so you would check for example
NSArray* arrayOfDicts = ...;
if ([arrayOfDicts isKindOfClass:[NSDictionary class]] arrayOfDicts = #[arrayOfDicts];
else if (! [arrayOfDicts isKindOfClass:[NSArray class]] arrayOfDicts = nil;
As others have pointed out, if any of the objects passed into the dictionary are nil, that will throw an exception that crashes your app. By doing the following:
[historialServicios addObject:#{
#"time_service": time_service,
#"id_service": id_service,
#"rate": rate,
#"destiny": destiny,
#"state": state,
#"origin": origin,
#"client_id":client_id,
#"date": date,
#"driverName":driverName,
#"driverLastname": driverLastname,
#"driverPhone": driverPhone,
#"driverId": driverId
}];
You're depending that all these objects (eg time_service, id_service, etc) are not nil. As you've pointed out, they can be nil, so you need to have a means of checking for each object you do. I would recommend using an NSMutableDictionary, making a category method that only adds the key/value pair if they are both not nil:
#implementation NSMutableDictionary (Util)
-(void)setObjectOrRemoveIfNil:(id)anObject forKey:(id<NSCopying>)aKey
{
if (anObject == nil)
{
[self removeObjectForKey:aKey];
}
else
{
[self setObject:anObject forKey:aKey];
}
}
#end
And then put together your dictionary like so:
NSMutableDictionary* values = [NSMutableDictionary dictionary];
[values setObjectOrRemoveIfNil:time_service forKey:#"time_service"];
[values setObjectOrRemoveIfNil:id_service forKey:#"id_service"];
//Keep going with the rest of your values.
Finally we use that dictionary like you did already:
[historialServicios addObject:values];
check the count for the dictionary
if ([cabdriverLevelDict count] == 0) {
NSLog("empty");
}
else{
// Do your stuff !!
}
if (![cabdriverLevelDict isKindOfClass:[NSNull class]] ){
//do something
}
try this
You can try
NSDictionary *employeeLevelDict = [cabdriverLevelDict objectForKey:#"employee"];
if (employeeLevelDict.count != 0)
{
// do something if dict is not empty
}
else
{
}];
I am parsing a CSV file multiple times with for loop, here I need to store these arrays one by one dictionary. There are very less questions in stack about adding NSArray to NSDictionary. I am parsing CSV with below code but I strucked at storing in NSDictionary, The program is terminating and showing warning at assigning string to dictionary
for (i=0; i<=57; i++) {
NSString *keysString = [csvArray objectAtIndex:i];
NSArray *keysArray = [keysString componentsSeparatedByString:#","];
NSLog(#"Serail No %d %#",i,keysArray);
NSString *string = [NSString stringWithFormat:#"%d", i];
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithObjects: keysArray forKeys: string];
}
NSMutableDictionary *dict = [[NSMutableDictionary alloc]init];
for (i=0; i<=57; i++) {
NSString *keysString = [csvArray objectAtIndex:i];
NSArray *keysArray = [keysString componentsSeparatedByString:#","];
NSString *key = [NSString stringWithFormat:#"serial%d",i];
[dict setObject:keysArray forKey:key];
}
To get back data from dictionary,
NSArray *array = [dict valueForKey:#"serial24"];//to get array 24.
If I understand you correctly, you want to add the arrays to a dictionary, with the key being the string value of integer i ? What you need to do is allocate the dictionary outside your loop -
NSMutableDictionary *dict=[NSMutableDictionary new];
for (i=0; i<=57; i++) {
NSString *keysString = [csvArray objectAtIndex:i];
NSArray *keysArray = [keysString componentsSeparatedByString:#","];
NSLog(#"Serial No %d %#",i,keysArray);
NSString *string = [NSString stringWithFormat:#"%d", i];
dict[string]=keysArray;
}
I am not sure why you would want to do this, because this is basically an array. You could simply do -
NSMutableArray *outputArray=[NSMutableArray new];
for (NSString *keysString in csvArray) {
NSArray *keysArray = [keysString componentsSeparatedByString:#","];
[outputArray addObject:keysArray];
}
list = ({
clouds = 24;
speed = "4.31";
temp = {
day = "283.84";
eve = "283.84";
night = "283.84";
};
}),
Please can anyone tell me what am I doing wrong - I want to display list-->temp-->day value in table first I am trying to get data in an array which is terminating.
Here is my code am I doing any wrong
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:dataBuffer options:-1 error:nil];
NSLog(#"%#",json);
NSMutableDictionary * list = [json objectForKey:#"list"];
NSMutableArray *arrays = [[NSMutableArray alloc]initWithCapacity:0];
for (NSDictionary *lists in [list allValues]) {
[arrays addObject:[list valueForKey:#"temp"]];
}
If you want to access day then use below line,
NSString *day = [json valueForKeyPath:#"list.temp.day"];
Your list is an array, so if you want to do your things without changing much, you can replace:
NSMutableDictionary * list = [json objectForKey:#"list"];
With:
NSMutableDictionary * list = [[json objectForKey:#"list"] objectAtIndex:0];