Reputation: 1869
I have the following json file and I am trying to parse it from my iOS app. I defined a method to parse the file but I don't know how to handle the integers, which are the IDs. I want to put the data in an array (promotions) which contains a title and an array of products (explained better below). Any suggestion or good reference?
Json file:
"promotions": {
"1": {
"title": "promotion title",
"product": {
"1": {
"title": "product title",
"description": "this is the description"
},
"2": {
"title": "product title",
"description": "this is the description"
}
}
},
"2": { "3": {
"title": "product title",
"description": "this is the description"
},
"4": {
"title": "product title",
"description": "this is the description"
}
}
}
}
These are my data classes:
Promotion { NSString *title; NSArray *products;}
Product { NSString *title; NSString *description;}
And my function to load the json and add all the objects in an array of promotions which contains, for each promotion, an array of products.
- (NSArray *) infoFromJSON{
NSURL *url=[NSURL URLWithString:urlJSON];
NSURLRequest *request = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData
timeoutInterval:30.0];
NSURLResponse *response;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
NSDictionary *jsonDictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSMutableArray *promotions = [[NSMutableArray alloc] init];
NSArray *array = [jsonDictionary objectForKey:@"promotions"];
NSLog(@"array: %@", array);
NSLog(@"items en array %d", [array count]);
NSLog(@"object 1 en array: %@", [array objectAtIndex:1]);
// Iterate through the array of dictionaries
for(NSDictionary *dict in array) {
Promotion *promotion= [[Promotion alloc] initWithJSONDictionary:dict];
// Add the promotion object to the array
[promotions addObject:promotions];
//Add the products to each promotion??
}
// Return the array of promotion objects
return promotions;
}
Upvotes: 1
Views: 3214
Reputation: 2117
Your JSON is not well defined, you must try to use something like:
[{"promotion_id": 1
"title": "promotion title",
"products": [{"product_id": 1,
"title": "product title",
"description": "this is the description"
},
{"product_id": 2,
"title": "product title",
"description": "this is the description"
},
...
]
},
{"promotion_id": 2
"title": "promotion title",
"products": [{"product_id": 3,
"title": "product title",
"description": "this is the description"
},
{"product_id": 4,
"title": "product title",
"description": "this is the description"
},
...
]
},
...
]
Then, to parse the JSON dictionaries into custom objects I would recommend you to use the category NSObject+Motis I've been working recently. It is very useful to map JSON dictionaries into your custom Objective-C objects.
Mainly, you must do:
@interface Promotion : NSObject
@property (nonatomic, assing) NSInteger promotionId;
@property (nonatomic, strong) NSString *title;
@property (nonatomic, strong) NSArray *products;
@end
@implementation Promotion
- (NSDictionary*)mjz_motisMapping
{
return @{@"promotion_id" : @"promotionId",
@"title" : @"title",
@"products" : @"products",
};
}
- (NSDictionary*)mjz_arrayClassTypeMappingForAutomaticValidation
{
return @{"products": [Product class]};
}
@end
@interface Product : NSObject
@property (nonatomic, assing) NSInteger productId;
@property (nonatomic, strong) NSString *title;
@property (nonatomic, strong) NSArray *productDescription;
@end
@implementation Promotion
- (NSDictionary*)mjz_motisMapping
{
return @{@"product_id" : @"productId",
@"title" : @"title",
@"description" : @"productDescription",
};
}
@end
and then perform the parsing by doing:
- (void)parseTest
{
NSData *data = jsonData; // <-- YOUR JSON data
// Converting JSON data into array of dictionaries.
NSError *error = nil;
NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
if (error)
return; // <--- If error abort.
NSMutableArray *promotions = [NSMutableArray array];
for (NSDictionary *dict in jsonArray)
{
Promotion *promotion = [[Promotion alloc] init];
[promotion mjz_setValuesForKeysWithDictionary:dict];
[promotions addObject:promotion];
}
}
You can read how it works in this post: http://blog.mobilejazz.cat/ios-using-kvc-to-parse-json
Hoping it helps you as much it helped me.
Upvotes: 6
Reputation: 1869
I finally ended up changing the json for:
{
"promotions": [
{
"id": "1",
"title": "promotion title",
"products": [
{
"id": "1",
"title": "product title",
"description": "description"
},
{
"id": "2",
"title": "product title",
"description": "description"
}
]
},
{
"id": "2",
"title": "promotion title",
"products": [
{
"id": "6",
"title": "product title",
"description": "description"
}
]
}
]
}
And this is how I parse the json:
- (NSArray *) infoFromJSON{
// Create a NSURLRequest with the given URL
NSURL *url=[NSURL URLWithString:urlJSON];
NSURLRequest *request = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData
timeoutInterval:30.0];
// Get the data
NSURLResponse *response;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
//Create an array to hold all the information
NSMutableArray *info = [[NSMutableArray alloc] init];
// Now create a NSDictionary from the JSON data
NSDictionary *jsonDictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSArray *arrayPromotions = [jsonDictionary objectForKey:@"promotions"];
for(NSDictionary *dictCategories in arrayPromotions) {
Block *promotion = [[Block alloc] initWithJSONDictionary:dictCategories];
NSArray *arrayProducts = [dictCategories objectForKey:@"products"];
promotion.questions = [[NSMutableArray alloc] init];
for(NSDictionary *dictProducts in arrayProducts) {
Product *product = [[Product alloc] initWithJSONDictionary:dictProducts];
NSLog(@"product title %@", product.title);
[promotions.product addObject:product];
}
[info addObject:promotion];
NSLog(@"Promotion: %@ product 2: %@", promotion.title, [[promotion.products objectAtIndex:1] title]);
}
// Return the array of Location objects
return info;
}
I defined and implemented the method initWithJSONDictionary in both data classes (Promotion and Product)
- (id)initWithJSONDictionary:(NSDictionary *)jsonDictionary {
if(self = [self init]) {
self.title = [jsonDictionary objectForKey:@"title"];
}
return self;
}
Upvotes: 0
Reputation: 119021
That's nasty JSON. If you can, get it changed. At the moment you have a number of dictionaries, where the keys in the dictionaries are numbers. These dictionaries should be arrays.
You have written your code as if they are arrays.
If you need to keep the JSON, read the dictionaries out and then iterate the key, or, if you can (because you aren't using the keys for sorting) just get all of the values as an array from the dictionary and iterate that.
Ideally, change the JSON and use RestKit...
Upvotes: 1