Reputation: 3335
I'm trying to sort a NSDictionary with the following code:
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:[str dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableLeaves error:&err];
for (NSDictionary* lesson in jsonDict[@"data"][@"lessons"]) {
data[lesson[@"day"]][lesson[@"index"]][@"title"] = lesson[@"title"];
}
If I log the values of lesson[@"day"]
and so on, the values seem to be correct. Somehow if I log data[@"1"][@"1"]
after the loop it's just empty. So the problems seems to be setting the values into the NSDictionary data.
The original JSON string contains a list with all lessons. To access them correctly I want to have a new NSDictionary in this format: data[day][index][field]
The JSON code looks like this:
{"status":"success","data":{"lessons":[{"id":1,"index":"1","day":"1","title":"Mathe","teacher":"Mr. xyz","room":"103","ind":"1"},{"id":2,"index":"1","day":"2","title":"Physik","teacher":"Mr xyz","room":"PH4","ind":"1"},...
Upvotes: 0
Views: 737
Reputation: 539745
The problem is (I assume) that
data[lesson[@"day"]][lesson[@"index"]][@"title"] = lesson[@"title"];
does not automatically create the intermediate dictionaries
data[lesson[@"day"]]
data[lesson[@"day"]][lesson[@"index"]]
You have to check first if they exist, and assign a mutable dictionary if they don't yet exist. (There is no Autovivification as with Perl hashes!) Something like:
if (data[lesson[@"day"]] == nil) {
data[lesson[@"day"]] = [NSMutableDictionary dictionary];
}
if (data[lesson[@"day"]][lesson[@"index"]] == nil) {
data[lesson[@"day"]][lesson[@"index"]] = [NSMutableDictionary dictionary];
}
data[lesson[@"day"]][lesson[@"index"]][@"title"] = lesson[@"title"];
Complete working code:
NSString *str = @"{\"status\":\"success\",\"data\":{\"lessons\":[{\"id\":1,\"index\":\"1\",\"day\":\"1\",\"title\":\"Mathe\",\"teacher\":\"Mr. xyz\",\"room\":\"103\",\"ind\":\"1\"},{\"id\":2,\"index\":\"1\",\"day\":\"2\",\"title\":\"Physik\",\"teacher\":\"Mr xyz\",\"room\":\"PH4\",\"ind\":\"1\"}]}}";
NSError *err;
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:[str dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableLeaves error:&err];
NSMutableDictionary *data = [NSMutableDictionary dictionary];
for (NSDictionary* lesson in jsonDict[@"data"][@"lessons"]) {
if (data[lesson[@"day"]] == nil) {
data[lesson[@"day"]] = [NSMutableDictionary dictionary];
}
if (data[lesson[@"day"]][lesson[@"index"]] == nil) {
data[lesson[@"day"]][lesson[@"index"]] = [NSMutableDictionary dictionary];
}
data[lesson[@"day"]][lesson[@"index"]][@"title"] = lesson[@"title"];
}
NSLog(@"%@", data);
Output:
{ 1 = { 1 = { title = Mathe; }; }; 2 = { 1 = { title = Physik; }; }; }
Upvotes: 2
Reputation: 52538
NSJSONSerialization creates dictionaries and arrays filled with other dictionaries, arrays, and values of type NSString, NSNumber, or NSNull.
You should re-think your strategy of writing hugely complex lines of code, but extract things one by one, to make it less confusing, and to make it possible to debug. Like
NSDictionary* data = jsonDict [@"data"];
NSArray* lessons = data [@"lessons"];
for (NSDictionary* lesson in lessons)
{
NSString* lessonDay = lesson [@"day"];
...
}
and so on (it will also make your code run a lot quicker if you don't lookup the same thing again and again and again and again).
Now to where your bug is: dict [@"key"] = data; calls setObject:forKey: . However, dict [@"key1"] [@"key2"] calls objectForKey: @"key1" on the dictionary, that will give you a nil value, and then setObjectForKey: will be called with a nil receiver.
Upvotes: 1