-2

Trying to parse nested json. Trying to grab the content within the nested json file. Appears to be an array of dictionaries. Within that we want a field that has dictionary content (posts). Then within that the custom_fields which is an array of an array.

///////////// ViewController.h //////////
@property (nonatomic, strong) NSMutableArray *jsonArray;     
@property (nonatomic, strong) NSMutableArray *postArray;   
@property (nonatomic, strong) NSMutableDictionary *fieldArray;   
@property (nonatomic, strong) NSMutableArray *testArray;   

- (void) retrieveData;

@end




/////////////////  ViewController.m   //////////////////

#import "ViewController.h"
#import "Model.h"

@interface ViewController ()

@end

@implementation ViewController
@synthesize jsonArray, postArray, fieldArray, testArray;

- (void)viewDidLoad {
    [super viewDidLoad];

    //Set title of VC
    self.title = @"SF";

    //Load data
    [self retrieveData];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    // Return the number of sections.
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:     (NSInteger)section {
    // Return the number of rows in the section.
    return fieldArray.count;
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView   dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

    //Configure cell:  
    Model * modelObject = [[Model alloc] init];
    modelObject = [fieldArray objectAtIndex:indexPath.row];
    cell.tag = indexPath.row;
    cell.textLabel.text = modelObject.address;
    NSLog(@"the text is %@", modelObject.address);

    //Accessory
    cell.accessoryType = UITableViewCellAccessoryNone; 
    cell.selectionStyle = UITableViewCellSelectionStyleNone; 

    return cell;
}

- (void) retrieveData
{
    NSURL * url = [NSURL URLWithString:getDataURL];
    NSData * data = [NSData dataWithContentsOfURL:url];

    jsonArray = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];

    //Set up arrays
    postArray = [[NSMutableArray alloc] init]; 
    fieldArray = [[NSMutableDictionary alloc] init];
    testArray = [[NSMutableArray alloc] init];

    NSLog(@"old post class: %@", NSStringFromClass([postArray class]));
    NSLog(@"old field class: %@", NSStringFromClass([fieldArray class]));
    NSLog(@"old test class: %@", NSStringFromClass([testArray class]));

    //Set up array from jsonArray
    postArray = [jsonArray valueForKey:@"posts"];
    fieldArray = [postArray valueForKey:@"custom_fields"];

    NSLog(@"new post class: %@", NSStringFromClass([postArray class]));
    NSLog(@"new field class: %@", NSStringFromClass([fieldArray class]));
    NSLog(@"new test class: %@", NSStringFromClass([testArray class]));

    NSLog(@"Test Array: %@", fieldArray);

    //Set up json array
    for (int i = 0; i < fieldArray.count; i++)
    {
        //Create object
        NSString * name = [[fieldArray valueForKey:@"cf_name"] objectAtIndex:i];
        //NSLog(@"name: %@", name);

        NSString * address = [[fieldArray valueForKey:@"cf_Address"] objectAtIndex:i];
        //NSLog(@"address: %@", address);

        NSString * contact = [[fieldArray valueForKey:@"cf_contact"] objectAtIndex:i];
        //NSLog(@"contact: %@", contact);
    }

    //Reload table view
    [self.tableView reloadData];
}

@end
Kevin
  • 1
  • 1
  • possible duplicate of [How can I debug 'unrecognized selector sent to instance' error](http://stackoverflow.com/questions/25853947/how-can-i-debug-unrecognized-selector-sent-to-instance-error) – Hot Licks Mar 07 '15 at 02:35
  • If your data link is to be believed, the outermost JSON structure is an object, not an array. Also, it's not mutable, since you did not specify the parsing option for that. The contents of "posts", however, *is* an array, and using `valueForKey` on it will return an array of "custom_fields" values, where each individual value is an NSDictionary. Asking for the "cf_Business_name" element for the nth entry of the "custom_fields" array will then return an NSArray, typically containing a single name. That is, what you think is an NSString is an NSArray, as the exception clearly tells you. – Hot Licks Mar 07 '15 at 02:46
  • You really need to clean up this mess, distinguish which things are arrays and which are dictionaries. And you cause a lot of wasted motion (and confusion) using `valueForKey` and its kin vs peeling apart the JSON in a more conventional fashion. – Hot Licks Mar 07 '15 at 02:48
  • And the exception stack trace would have told you exactly where the error was, if you had looked at it. – Hot Licks Mar 07 '15 at 02:52
  • It would appear the values within custom_fields are arrays (e.g. cf_Business_Name, cf_Address....). The structure of the json is: – Kevin Mar 07 '15 at 18:54
  • I think I already said that. – Hot Licks Mar 07 '15 at 18:57
  • I would appear overall json (array), posts (array or dictionary), custom_fields (dictionary), cf_Business_Name (array). How to get the values of cf_Business_Name and other values? I recall trying to set all of the custom field values as NSMutableArray instead of NSString and it gave me an error. – Kevin Mar 07 '15 at 19:02
  • First, go to json.org and learn how to read JSON. Then throw away the examples, sit down, and write code. Do one layer at a time -- parse the JSON, extract the "posts" array (as an NSArray), iterate through the array, treating each array element as the NSDictionary it is. From each NSDictionary extract the "custom_fields" object (as an NSDictonary), then extract, eg, "cf_Business_Name" from that, as the NSArray that it is. Access the NSString that is the only element of that array. NSLog each step along way, for starters, noting that arrays appear in `( )` while dictionaries are in `{ }`. – Hot Licks Mar 07 '15 at 19:09
  • I don't understand. Because I did NSLog(@"Value, %@", promoObject.businessName)..... This gave me a value. What the correct way of getting the value other than promoObject.businessName? What you're saying is it is a deeper problem of incorrect typecasting? – Kevin Mar 07 '15 at 19:15
  • Okay thank you. Test out now – Kevin Mar 07 '15 at 19:17
  • Look carefully at what NSLog displays. If it's "( something )" (note the `( )` characters) that means that you have an array with "something" in it. If it's "{ somekey = somevalue }" that means you have a dictionary. – Hot Licks Mar 07 '15 at 22:39

2 Answers2

0

The problem is exactly like the error describes. You're trying to call isEqualToString: on an NSArray, which causes a crash. I'm not sure where exactly you're doing the comparison, but it's happening. It's likely caused by the fact you are using valueForKey: when you are parsing the JSON instead of objectForKey:.

AdamPro13
  • 7,232
  • 2
  • 30
  • 28
  • I tried objectForKey before, but that gives me a "objectForKey may not work with postArray" and "objectForKey may not work with fieldArray". I – Kevin Mar 07 '15 at 18:52
  • Using `valueForKey` will return an array when used on an array of dictionaries (which is the case in most of it's uses above). This is a useful feature if you understand it, but highly confusing if you don't. – Hot Licks Mar 07 '15 at 18:59
0

It was tricky. I have to thank Hot Licks!

postVal = valueForKey on the JSONData turned output into array.

Than I iterate through the array of dictionaries as follows

for (NSMutableDictionary *postDict in postVal) {}

Within that I wanted a field within the dictionary. So I used the following:

id key;
while((key = [enumerator nextObject])) {}

After that, all key's were strings, but the values were array. To get the array as a string, I used the following

NSString * bName = [fieldVal objectForKey:key][0];

Type is finally NSString!!!!!!!

Thank you.

Kevin
  • 1
  • 1