0

I am trying to use the data which I read from a text file in objective c. The data I read from the text file is:

{"aps":{"alert":"Test 1!","sound":"beep.wav","badge":5,"Type":"Banking"},"acme1":"bar","acme2":42}|{"aps":{"alert":"Test 2!","sound":"beep.wav","badge":5,"Type":"Banking"},"acme1":"bar","acme2":42}|{"aps":{"alert":"Test 3!","sound":"beep.wav","badge":5,"Type":"Banking"},"acme1":"bar","acme2":42}|{"aps":{"alert":"Test 4!","sound":"beep.wav","badge":5,"Type":"Banking"},"acme1":"bar","acme2":42}|{"aps":{"alert":"Test 5!","sound":"beep.wav","badge":5,"Type":"Banking"},"acme1":"bar","acme2":42}

Once read, I split the file into an array with a delimiter of "|". I then want to further separate it into 3 different arrays: banking, fraud and investment based on the key "Type". However I cannot seem to reach parse the JSON string once I split it into the array. My view did load method is below:

- (void)viewDidLoad {

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *fileName = [NSString stringWithFormat:@"%@/AccountNotifications.txt", documentsDirectory];
    NSString *fileContents = [[NSString alloc]  initWithContentsOfFile:fileName usedEncoding:nil error:nil];
    NSArray *fileData = [fileContents componentsSeparatedByString:@"|"];

    if (fileContents != NULL)
    {
        bankingNotifications =  [[NSMutableArray alloc] init];
        fraudNotifications =  [[NSMutableArray alloc] init];
        investmentNotifications = [[NSMutableArray alloc] init];        

        for (i = 0; i < [fileData count]; i++)
        {
            NSString *notification = fileData[i];
            NSDictionary *json = [notification JSONValue];
            NSArray *items = [json valueForKeyPath:@"aps"];

            if ([[[items objectAtIndex:i] objectForKey:@"Type"] isEqual: @"Banking"])
            {
                [bankingNotifications addObject:fileData[i]];
                NSLog(@"Added object to banking array");
            }

            if ([[[items objectAtIndex:i] objectForKey:@"Type"] isEqual: @"Fraud"])
            {
                [fraudNotifications addObject:fileData[i]];
                NSLog(@"Added object to fraud array");

            }

            if ([[[items objectAtIndex:i] objectForKey:@"Type"] isEqual: @"Investment"])
            {
                [investmentNotifications addObject:fileData[i]];
                NSLog(@"Added object to investment array");

            }
        } }

There is an error with these three lines:

    NSString *notification = fileData[i];
    NSDictionary *json = [notification JSONValue];
    NSArray *items = [json valueForKeyPath:@"aps"];

Could you please help me parse the JSON strings into the three mutable arrays? The error I am getting is:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSDictionaryM objectAtIndex:]: unrecognized selector sent to instance 0x1d59db30'

4
  • The error you posted says that you are trying to use objectAtIndex, an NSArray method, on a NSDictionary. Which line was it bombing out on? Commented Feb 28, 2013 at 22:22
  • 1
    '-[__NSDictionaryM objectAtIndex:]: unrecognized selector sent to instance means you're trying to treat a dictionary like an array. (Read the message carefully and you can see that.) The separated strings you're getting represent JSON "objects" (dictionaries), not arrays (and the next layer in are "objects" too), so that's likely your problem. (And YOY are the strings separated like that vs just putting them into an enveloping JSON array???) Commented Feb 28, 2013 at 22:29
  • This is where you start to go wrong: NSArray *items = [json valueForKeyPath:@"aps"];. The result of that operation is an NSDictionary, not an NSArray. Commented Feb 28, 2013 at 22:31
  • shouldn't you just put 3 arrays in your file instead of using '|'? That will make it a conforming JSON file. Commented Feb 28, 2013 at 22:47

2 Answers 2

3

If you create the text file yourself I would suggest you create a valid json object (as your data looks like it is supposed to be json) to keep your data nice and clean. similar to this:

{"aps":[{"type":"Banking","badge":5},{"Type":"Fraud","badge":12}]}

Then you can do following (this code is not tested, it can be that you have to amend it a bit) but i hope you'll get an idea :)

NSError*    error       = nil;
NSDictionary*    dict = nil;
//serialising the jsonobject to a dictionary
dict  = [NSJSONSerialization JSONObjectWithData:fileContents
                                              options:kNilOptions
                                                error:&error];
bankingNotifications =  [[NSMutableArray alloc] init];
fraudNotifications =  [[NSMutableArray alloc] init];
investmentNotifications = [[NSMutableArray alloc] init];

if (dict) {
    NSArray *dataArray = [dict objectForKey:@"aps"];
    NSDictionary* siteData    = nil;
    NSEnumerator* resultsEnum   = [dataArray objectEnumerator];
    while (siteData = [resultsEnum nextObject])
    {
        //
        if( [[siteData objectForKey:@"Type"] isEqualToString: @"Banking"]) {
            [bankingNotifications addObject:notification];
            NSLog(@"Added object to banking array");
        } else if ([[siteData objectForKey:@"Type"] isEqualToString: @"Fraud"])
        {
            [fraudNotifications addObject:notification];
            NSLog(@"Added object to fraud array");
        }
        else if ([[siteData objectForKey:@"Type"] isEqualToString: @"Investment"])
        {
            [investmentNotifications addObject:notification];
            NSLog(@"Added object to investment array");
        }

    }
}
Sign up to request clarification or add additional context in comments.

Comments

1

The value for Key "aps" is a dictionary.

    NSDictionary *item = [json valueForKeyPath:@"aps"];

    if ([[item objectForKey:@"Type"] isEqualToString: @"Banking"])
    {
        [bankingNotifications addObject:notification];
        NSLog(@"Added object to banking array");
    } 
    else if ([[item objectForKey:@"Type"] isEqualToString: @"Fraud"])
    {
        [fraudNotifications addObject:notification];
        NSLog(@"Added object to fraud array");
    }
    else if ([[item objectForKey:@"Type"] isEqualToString: @"Investment"])
    {
        [investmentNotifications addObject:notification];
        NSLog(@"Added object to investment array");
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.