简体   繁体   中英

Parsing Nested NSDictionary and NSArray Data in xCode

I have a complex JSON file that I need to parse into a CoreData table. Currently, I capture the data into an NSArray with this format and the following 6 elements:

 2013-08-29 10:54:04.930 iTrackTest[1542:c07] athleteRecords[0]: @SchoolID
 2013-08-29 10:54:04.930 iTrackTest[1542:c07] athleteRecords[1]: @LastName
 2013-08-29 10:54:04.930 iTrackTest[1542:c07] athleteRecords[2]: @Gender
 2013-08-29 10:54:04.931 iTrackTest[1542:c07] athleteRecords[3]: SchType
 2013-08-29 10:54:04.931 iTrackTest[1542:c07] athleteRecords[4]: @FirstName
 2013-08-29 10:54:04.931 iTrackTest[1542:c07] athleteRecords[5]: @IDAthlete

First question, it appears that SchType is a k-dimensional NSArray of NSDictionaries. Is that true?

I have been capturing simpler, single-tiered JSON files using code from Paul Hegarty of Stanford:

 dispatch_async(fetchQ, ^{
    NSArray *athleteRecords;
    athleteRecords = [AthleticNetDataFetcher retrieveDataForAthleteWithID:athleteID];
    NSLog(@"In %@: athleteRecords has %d records",NSStringFromClass([self class]), [athleteRecords count]);
    NSLog(@"NSArray with athleteRecords: %@", athleteRecords);

    [document.managedObjectContext performBlock:^{ 
        int iCount=0;
        for (NSDictionary *athleteInfo in athleteRecords) {
            [self resultsWithAthleteInfoForAthleteWithID:athleteInfo inManagedObjectContext:document.managedObjectContext];
            NSLog(@"athleteRecords[%d]: %@", iCount, athleteInfo);
            iCount++;
        }
        [document saveToURL:document.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:NULL];

    }];
});

I need data elements from each node for every record in my CoreData table. For example, SchoolName from School node, IDSeason from Season node, and all elements from Results node would be written to a single CoreData table row (record).

Do I need to resort to dot notation and abandon the iteration through the NSArray or do I need to capture multiple NSArrays each with data further down the nodes? Having a hard time getting my head around this.

Thanks!

Not sure why I had such a difficult time getting my head around this, but Hot Licks got me on the right track.

Here is what I learned that might be helpful to others:

If you have multiple NSDictionaries embedded within an array, it is much simpler to parse these sub-dictionaries in other methods.

+(void)parseDivisionBranches:(NSDictionary *)schTypeDictionary usingStudentInfoFrom:(NSDictionary *)myAthleteInfo
          intoManagedDoc: (UIManagedDocument *)document
{

NSArray* schoolDivisions = [self wrapDictionaryInArrayIfNecessary:[schTypeDictionary valueForKeyPath:@"School.SchoolDivision"]];

for (NSDictionary* schoolDivision in schoolDivisions) {

        [MarksFromMeets  parseDictionaryWithXcMarksForAthlete:(NSString*) [myAthleteInfo objectForKey:@"athlete_ID"]
                                     fromDictionary:(NSDictionary *)schoolDivision
                                     intoThisManagedDoc:(UIManagedDocument *)document];
    }
}

In instances where only a single NSDictionary is passed at a particular level of the tree, it is simpler to embed that NSDictionary inside an NSArray so that you can use the same code to extract data; therefore, I always check to see if have an NSArray or NSDict.

+ (NSArray*) wrapDictionaryInArrayIfNecessary:(NSObject*)dictionaryMasquaradingAsAnArray

{ NSMutableArray* newArray = [[NSMutableArray alloc] init];

if([dictionaryMasquaradingAsAnArray isKindOfClass:[NSArray class]]) {
        newArray = [dictionaryMasquaradingAsAnArray copy];
    }else if([dictionaryMasquaradingAsAnArray isKindOfClass:[NSDictionary class]]) {
        [newArray addObject:dictionaryMasquaradingAsAnArray];
    }else {
        NSString *className = NSStringFromClass([dictionaryMasquaradingAsAnArray class]);
        NSLog(@"ERROR - dictionaryMasquaradingAsAnArray of %@ class", className);
        newArray = nil;
    }
return newArray;
}

Then parse each sub-dictionary in turn by calling the method associated with the branch of the data tree, in this case:

+ (void)parseDictionaryWithXcMarksForAthlete:(NSString*)withAthleteID
                            fromDictionary:(NSDictionary *)dictionary
                        intoThisManagedDoc:(UIManagedDocument *)document
{

NSArray* seasons = [self wrapDictionaryInArrayIfNecessary:[dictionary valueForKeyPath:@"Season"]];

BOOL* parsedSeasonData;
    for (NSDictionary* season in seasons) {
    parsedSeasonData = [self parseDictionaryWithSeasonsListings:(NSString*)withAthleteID
                                                 fromDictionary:(NSDictionary *)season
                                             intoThisManagedDoc:(UIManagedDocument *)document];

    }

}

At some nodes, I had to capture data and pass it along down the chain for use later when I would ultimately write a record to CoreData. Again, thanks to Hot Licks and hope this helps others.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM