Better JSON parsing implementation in Objective
I am receiving below JSON response for saving user preferences in core data.
preferences={
1={
children=({
3=Samsung;4=Nokia;
});id=1;name=Mobiles;
};2={
children=({
5="Samsung Curve TV";
});id=2;name=Electronics;
};
};
Here is my code snippet which is working fine. But I think this is much verbose code.
NSLog(@"Preferences: %@", [response objectForKey:@"preferences"]);
for (NSDictionary *dic in [response objectForKey:@"preferences"]) {
NSLog(@"ID: %@", [[[response objectForKey:@"preferences"] objectForKey:dic] objectForKey:@"id"]);
NSLog(@"NAME: %@", [[[response objectForKey:@"preferences"] objectForKey:dic] objectForKey:@"name"]);
NSLog(@"Children DIC: %@", [[[[[response objectForKey:@"preferences"]
objectForKey:dic] objectForKey:@"children"] objectAtIndex:0] objectForKey:@"3"]);
for (NSDictionary *childDic in [[[[response objectForKey:@"preferences"]
objectForKey:dic] objectForKey:@"children"] objectAtIndex:0]) {
NSLog(@"Child Name: %@", [[[[[response objectForKey:@"preferences"]
objectForKey:dic] objectForKey:@"children"] objectAtIndex:0] objectForKey:childDic]);
}
}
I have 3 questions.
How can I improve my code snippet? is there any shorter way to implement this?
Is this JSON response is good enough for mobile end parsing? is it good JSON format? Is there any JSON response format we should follow as Mobile developers in terms of using Core data (which simply reduces DB implementation as best practice)?
How do I construct a JSON string like this again from Objective-c?
Ok so, (Sorry for NOT deep analysis) first of all I'd modify your JSON not to contain dictionary
for dynamic elements (samsung has key 3 and so on, it should be array, make sense?)
I come up with imho better JSON structure:
{
"preferences":[
{
"items":[
{
"id" : "3",
"name" : "Samsung"
},
{
"id" : "3",
"name" : "Nokia"
}
],
"id":"1",
"name":"Mobiles"
},
{
"items":[
{
"id" : "3",
"name" : "Nokia"
}
],
"id":"2",
"name":"Electronics"
}
]
}
It's really easy now to map it to objects with JSONModel
and only one thing you should care about is mapping keys.
NSString *JSONString = @" { "preferences":[ { "items":[ { "id" : "3", "name" : "Samsung" }, { "id" : "3", "name" : "Nokia" } ], "id":"1", "name":"Mobiles" }, { "items":[ { "id" : "3", "name" : "Nokia" } ], "id":"2", "name":"Electronics" } ] }";
NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:[JSONString dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil];
NSError *mapError;
GlobalPreferences *globalPreferences = [[GlobalPreferences alloc] initWithDictionary:dictionary error:&mapError];
if (mapError) {
NSLog(@"Something went wrong with mapping model %@", mapError);
}
NSLog(@"Your mapped model: %@", globalPreferences);
Models:
Kinda GlobalPreference, root model, in case if u decide to add something extra
#import <JSONModel/JSONModel.h>
#import "Preference.h"
@interface GlobalPreferences : JSONModel
@property (nonatomic, strong) NSArray<Preference> *preferences; // using protocol here you specifying to which model data should be mapped
@property (nonatomic, strong) NSArray<Optional> *somethingElse; // some other settings may be here
@end
#import "GlobalPreferences.h"
@implementation GlobalPreferences
@end
Preference
#import <JSONModel/JSONModel.h>
#import "PreferenceItem.h"
@protocol Preference <NSObject>
@end
@interface Preference : JSONModel
@property (nonatomic, strong) NSNumber *ID; // required
@property (nonatomic, strong) NSString *name; // required
@property (nonatomic, strong) NSArray<PreferenceItem> *items;
@end
#import "Preference.h"
@implementation Preference
#pragma mark - JSONModel
+ (JSONKeyMapper *)keyMapper {
return [[JSONKeyMapper alloc] initWithDictionary:@{
@"id": @"ID",
}];
}
@end
PreferenceItem
#import <JSONModel/JSONModel.h>
// This protocol just to let JSONModel know to which model needs to be parsed data in case if it's an array/dictionary
@protocol PreferenceItem <NSObject>
@end
@interface PreferenceItem : JSONModel
@property (nonatomic, strong) NSNumber *ID;
@property (nonatomic, strong) NSString *name;
@end
#import "PreferenceItem.h"
@implementation PreferenceItem
#pragma mark - JSONModel
+ (JSONKeyMapper *)keyMapper {
return [[JSONKeyMapper alloc] initWithDictionary:@{
@"id": @"ID",
}];
}
@end
Should be ok for coreData
.
Maybe for you case all this is not necessary, but there are lot of things you need to care when u parsing/mapping network response such es data types
, missing keys
, error handling
and so on. If u map it manually - you risk to have broken app some day.
I know you asked best practices for Objective-C, but I would suggest switching to Swift and using SwiftyJSON. With Swift the code is much more readable than with Objective-C.
let prefs = json["preferences"]
let userName = prefs["id"].stringValue
let name = prefs["name"].stringValue
let child = prefs["children"].arrayValue[0].arrayValue[3]
https://github.com/SwiftyJSON/SwiftyJSON
You can easily build your own JSON structures and send them with Alamofire:
let parameters: [String : AnyObject] = [
"preferences": [
"id": "123",
"name": "John",
"children": [
["3": "Three"]
]
]
]
let urlReq = NSMutableURLRequest(url)
urlReq.HTTPMethod = .POST
let req = Alamofire.ParameterEncoding.JSON.encode(urlReq, parameters: parameters).0
let request = Alamofire.request(req)
https://github.com/Alamofire/Alamofire
链接地址: http://www.djcxy.com/p/48076.html上一篇: 什么是REST API响应的正确方法?