Getting values when NSDictionary contains a list - objective-c

I am being passed a dictionary:
aDictionary
When I log it out the dictionary has the following format:
{
value1 = "subValue1 {label=value1, info1=, info2=}";
value2 = "subValue2 {label=value2, info1=, info2=}";
value3 = "subValue3 {label=value2, info1=, info2=}";
}
I need to iterate over the dictionary and then determine if there is a value for value3 -> subValue3 -> info2.
I can do the initial iteration and I can make a subdictionary of the line:
"subValue3 {label=value2, info1=, info2=}"
But when I try to use it, say to get a count of the keys, I get -[subValue3 allKeys]: unrecognized selector sent to instance.
NSArray *keys;
int i, count;
id key, value;
keys = [aDictionary allKeys];
count = [keys count];
for (i = 0; i < count; i++)
{
key = [keys objectAtIndex:i];
value = [aDictionary objectForKey:key];
NSLog (#"Key: %# for value: %#", key, value);
NSDictionary *subDictionary = [aDictionary objectForKey:key];
if ([key isEqualToString:#"info2"]) {
DLog(#"subDictioanry = %#", subDictionary);
// Everything is fine up to here
NSArray *keys2;
int i2, count2;
id key2, value2;
keys2 = [subDictionary allKeys];
count = [keys2 count];
//
// Right here I get "-[subValue3 allKeys]: unrecognized selector sent to instance"
//
for (i2 = 0; i2 < count2; i2++) {
key2 = [keys2 objectAtIndex:i2];
value = [subDictionary objectForKey:key];
DLog (#"Key: %# for value: %#", key2, value2);
NSDictionary *subDictionary2 = [subDictionary objectForKey:key2];
DLog(#"subDictionary2 = %#", subDictionary2);
}
}
Questions:
I am not sure what the format of that second group of values is ("subValue3 {label=value2, info1=, info2=}"). Is it a set, an array, a dictionary?
How do I get that group into a dictionary (without failing on the key(?) "subValue3") so that I can check if the key info2 has any value?
Disclaimers:
I know there are more efficient ways to iterate over a dictionary, I'm just trying to be as clear as possible.
I'm sure there is just something basic I'm missing but I am not seeing the answer in the Apple docs on iteration or NSDictionary nor am I finding anything about the format in that second group.
Thanks!

right now "subValue1 {label=value1, info1=, info2=}"; is a NSString. So allKeys of a NSString will crash.
Infact does this "subValue1 {label=value1, info1=, info2=}"; look like a valid json. I dont think this is a valid JSON. Even jsonlint.com thinks so.
This is a valid json
{
"subValue1": {
"label": "value1",
"info1": "",
"info2": ""
}
}
After you construct json like so, then use NSJSONSerialization to convert -
NSError *e = nil;
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:data options: NSJSONReadingMutableContainers error: &e];
if (!jsonDict)
{
NSLog(#"Error parsing JSON: %#", e);
} else
{
for(NSDictionary *item in jsonDict)
NSLog(#"Item: %#", item);
}

Related

Parse NSDictionary in NSArray created from JSON in Objective-C

I'm trying to get information out of this Dictionary that was created from a JSON string. The JSON string is returned from the server and is put in a dictionary. That dictionary is passed to myMethod that is suppose to break it down so I can get the information that each record contains.
The "Recordset" is an Array. The Record is also an array of dictionaries.
How do I get to the dictionaries? I keep getting NSDictionaryM objectAtIndex: unrecognized selector sent to instance
Recordset = (
{
Record = (
{
MODMAKlMakeKey = 1112;
MODlModelKey = 1691;
MODvc50Name = "10/12 Series 2";
},
{
MODMAKlMakeKey = 1112;
MODlModelKey = 1687;
MODvc50Name = "10/4";
},
{
MODMAKlMakeKey = 1112;
MODlModelKey = 1686;
MODvc50Name = "10/6";
},
etc .. etc... ( about 100 records )
Here is what I have
- (void) myMethod : (NSDictionary*) dictionary {
//INITIAL
NSArray * arrRecordSet = [dictionary objectForKey:#"Recordset"];
NSArray * arrRecord = [arrRecordSet objectAtIndex:0];
NSDictionary * theRecord = [NSDictionary dictionaryWithObjects:arrRecord forKeys:[arrRecord objectAtIndex:0]];
for (int i = 0; i < arrRecord.count; i++) {
NSLog(#"MODMAKlMakeKey: %#", [theRecord objectForKey:#"MODMAKlMakeKey"]);
}
}
Try this
NSArray * arrRecord = [arrRecordSet objectForKey:#"Record"];
Try to check first if the return of [dictionary objectForKey:#"Recordset"] is really a dictionary or an array.
To do this:
if([[dictionary objectForKey:#"Recordset"] isKindOfClass:[NSArray class]]) {
//object is array
}
else if ([[dictionary objectForKey:#"Recordset"] isKindOfClass:[NSDictionary class]]) {
//object is dictionary
}

Updating key in NSMutableDictionary

json is a NSMutableDictionary with a key "message". I need to "clean" the data in that key using stringByReplacingOccurrencesOfString
NSLog(#"json: %#", json); outputs this:
json: {
conversationId = 61;
countmessagesinconversation = 2;
message = "Messages exist!";
messagesinconversation = (
{
message = "Hi";
messagecreated = "June 24, 2013 16:16";
messageid = 68;
sentby = Thomas;
sentbyID = 1;
title = "Subject";
},
{
message = "What's up?";
messagecreated = "September 22, 2013 17:00";
messageid = 331;
sentby = Steve;
sentbyID = 2;
title = "Subject";
}
);
success = 1;
}
So, this is what I've come up with, but I'm clearly getting it all wrong.
NSString *newstr = [[NSString alloc]init];
for (newstr in [[[json objectForKey:#"messagesinconversation"]allKeys]copy]){
newstr = [newstr stringByReplacingOccurrencesOfString:#" "
withString:#""];
[json setValue:newstr forKey:#"message"];
}
Could somebody please help me out with this and explain so I understand the concept? I know how to do this with an array but what my problem is (I think) is that I do not fully understand how to access the right key in the dictionary.
Edit: Sorry for not being clear in my question. What happens is that if there are two space characters in the key message then " " shows up when I display it on the screen.
//First get the array of message dictionaries:
NSArray * messages = [json objectForKey:#"messagesinconversation"];
//create new array for new messages
NSMutableArray * newMessages = [NSMutableArray arrayWithCapacity:messages.count];
//then iterate over all messages (they seem to be dictionaries)
for (NSDictionary * dict in messages)
{
//create new mutable dictionary
NSMutableDictionary * replacementDict = [NSMutableDictionary dictionaryWithDictionary:dict];
//get the original text
NSString * msg = [dict objectForKey:#"message"];
//replace it as you see fit
[replacementDict setObject:[msg stringByReplacingOccurrencesOfString:#" " withString:#""] forKey:#"message"];
//store the new dict in new array
[newMessages addObject:replacementDict];
}
//you are done - replace the messages in the original json dict
[json setObject:newMessages forKey:#"messagesinconversation"];
Add your array of dictionary in another mutable array
NSMutableArray *msgArray = [[json objectForKey:#"messagesinconversation"] mutableCopy];
Use for loop for access it.
for (int i = 0 ; i < msgArray.count ; i++)
{
[[[msgArray objectAtindex:i] objectForKey:#"message"] stringByReplacingOccurrencesOfString:#" " withString:#""];
}
[self.mainJSONDic setValue:msgArray forKey:#"messagesinconversation"];
Try this code might helpful in your case:
Now that the requirements are more clear I'll try an answer. I try to use the same names as in your question and suggested in erlier answers.
Make json an NSMUtableDictionary where you declare it. Then go forward:
json = [json mutableCopy]; // creates a mutable dictionary based on json which is immutable as result of the json serialization although declared as mutable.
NSMutableArray *msgArray = [[json objectForKey:#"messagesinconversation"] mutableCopy]; //this fetches the array from the dictinary and creates a mutable copy of it.
[json setValue:newstr forKey:#"messagesinconversation"]; // replace the original immutable with the mutable copy.
for (int i = 0; i < [msgArray count]; i++) {
NSMutableDictionary mutableInnerDict = [[msgArray objectAtIndex:i] mutableCopy]; // fetching the i-th element and replace it by a mutable copy of the dictionary within.
[msgArray replaceObjectAtIndex:i withObject:mutableInnerDict]; // it is now mutable and replaced within the array.
NSString *newString = [[[msgArray objectAtindex:i] objectForKey:#"message"] stringByReplacingOccurrencesOfString:#" " withString:#" "]; // crates a new string with all &nbsp removed with blanks.
[mutableInnerDict setValue:newString forKey:#"message"];
}
Regarding the replacement of &nbsp with " ", is this really what you want? I am asking because &nbsp does not occur in your sample data. Or do you want to remove blanks at all?

all Keys and Objects from a NSDictionary to a NSString

I've got a NSDictionary and I'd like put all of it's objects and keys into a NSString, so that I can finally display them in a label like this:
key1: object1
key2: object2
key3: object3
... ...
Any ideas?
Build the string and then set it to the labels text.
NSMutableString *myString = [[NSMutableString alloc] init];
[dictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
[myString appendFormat:#"%# : %#\n", key, obj];
}];
self.label.text = myString;
Note
The docs (String Programming Guide) for the %# format specifier state:
%#
Objective-C object, printed as the string returned by descriptionWithLocale: if available, or description otherwise. Also works with CFTypeRef objects, returning the result of the CFCopyDescription function.
So if these are your own custom objects in the dictionary you will most likely need to override the description method to provide more meaningful output
Update
You mention that you need your output sorted by keys - dictionaries are not ordered so you will have to do it differently - this example assumes that your keys are strings
NSArray *sortedKeys = [[dictionary allKeys] sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)];
NSMutableString *myString = [[NSMutableString alloc] init];
for (NSString *key in sortedKeys) {
[myString appendFormat:#"%# : %#\n", key, [dictionary objectForKey:key]];
}
self.label.text = myString;
try this
for(id key in [dictionary allKeys])
{
id value = [dictionary objectForKey:key];
NSLog(#"%# : %#", key, value);
}
NSString *row;
for (id key in dictionary) {
row = [NSString stringWithFormat:"%#: %#", key, [dictionary objectForKey:key]];
// do something with your row string
}
Iam trying to append two time values from my TCTime object and display in label, even though I added "\n" towards the end it is printing only the first value but not the second value.
_feedTimes is NSArray.
NSMutableString *myString = [[NSMutableString alloc] init];
TCTime *time = _feedTimes[indexPath.row];
[myString appendFormat:#"%s : %#\n", "Time 1 ", time.Time1];
[myString appendFormat:#"%s : %#\n", "Time 2 ", time.Time2];
self.label.text = myString;

Parsing multiple row from json info in objective-c

My json stiring is:
{
"locations" :[
{
id = 0;
lat = "41.653048";
long = "-0.880677";
name = "LIMPIA";
},
{
id = 1;
lat = "41.653048";
long = "-0.890677";
name = "LIMPIA2";
}
]
}
Using:
NSDictionary * root = [datos_string1 JSONValue];
NSArray *bares = (NSArray *) [root objectForKey:#"locations"];
for (NSArray * row in bares) {
NSString *barName1 = [bares valueForKey:#"name"];
NSLog(#"%#",barName1);
}
I obtain from NSlog , twice otput
(
LIMPIA,
LIMPIA2
)
So somthing is wrong. I need to estract di single value parameter (lat, lon and nombre) for each item (in order to use in a mapkit app). Could you help me?
I need to estract di single value parameter (lat, lon and nombre) for each item (in order to use in a mapkit app)
If I understand your question correctly, you're trying to access each value in each dictionary in the locations array, is that right?
In order to access each value (if that is indeed your question), this should work:
NSDictionary *root = [datos_string1 JSONValue];
NSArray *bares = (NSArray *)[root objectForKey:#"locations"];
// Each item in the array is a dictionary, not an NSArray
for (NSDictionary *dict in bares) {
// Loop over keys
for (NSString *key in [dict allKeys]) {
NSLog(#"dict[%#] == %#", key, [dict objectForKey:key]);
}
}

complex JSON parsing using Objective-C

{
"Flight1":{
"3":{
"id":"10",
"name":"JumboJet1B",
"level":"1",
"category":"1",
"energy":"10",
"bonus":"10",
"completed":0
},
"4":{
"id":"10",
"name":"JumboJet1B",
"level":"1",
"category":"1",
"energy":"10",
"bonus":"10",
"completed":0
}
}
}
This was the json output
How can I parse inside the items of 3 and 4, say getting the id, energy and name
Thanks!
If the order inside Flight1 doesn’t matter, the following should work:
NSDictionary *flights = … // result from a JSON parser
NSDictionary *flight1 = [flights objectForKey:#"Flight1"];
for (NSString *key in [flight1 allKeys]) {
NSDictionary *flight1Entry = [flight1 objectForKey:key];
NSString *entryId = [flight1Entry objectForKey:#"id"];
NSString *entryName = [flight1Entry objectForKey:#"name"];
NSString *entryEnergy = [flight1Entry objectForKey:#"energy"];
…
}
Otherwise, if you want the keys sorted according to their numeric value:
NSDictionary *flights = … // result from a JSON parser
NSDictionary *flight1 = [flights objectForKey:#"Flight1"];
NSArray *flight1Keys = [[flight1 allKeys] sortedArrayUsingComparator:^(id o1, id o2) {
NSInteger i1 = [o1 integerValue];
NSInteger i2 = [o2 integerValue];
NSComparisonResult result;
if (i1 > i2) result = NSOrderedDescending;
else if (i1 < i2) result = NSOrderedAscending;
else result = NSOrderedSame;
return result;
}];
for (NSString *key in flight1Keys) {
NSDictionary *flight1Entry = [flight1 objectForKey:key];
NSString *entryId = [flight1Entry objectForKey:#"id"];
NSString *entryName = [flight1Entry objectForKey:#"name"];
NSString *entryEnergy = [flight1Entry objectForKey:#"energy"];
…
}
Assuming that you are using the json framework you could access it like this:
NSDictionary *jsonDict = [jsonString JSONValue];
NSString *id = [[[jsonDict objectForKey:#"Flight1"] objectForKey:#"3"] objectForKey:#"id"];
This assumes alot, so make use of try except blocks or iterate through the different levels.