Ios Objective-c中更好的JSON解析实现和最佳实践?
我收到以下JSON响应,用于在核心数据中保存用户首选项Ios Objective-c中更好的JSON解析实现和最佳实践?,ios,json,web-services,parsing,Ios,Json,Web Services,Parsing,我收到以下JSON响应,用于在核心数据中保存用户首选项 preferences={ 1={ children=({ 3=Samsung;4=Nokia; });id=1;name=Mobiles; };2={ children=({ 5="Samsung Curve TV"; });id=2;name=Electronics; }; }; 这是我的
preferences={
1={
children=({
3=Samsung;4=Nokia;
});id=1;name=Mobiles;
};2={
children=({
5="Samsung Curve TV";
});id=2;name=Electronics;
};
};
这是我的代码片段,运行良好。但我认为这是非常冗长的代码
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]);
}
}
我有三个问题
我知道您询问了Objective-C的最佳实践,但我建议切换到Swift并使用SwiftyJSON。使用Swift,代码比使用Objective-C可读性更强
let prefs = json["preferences"]
let userName = prefs["id"].stringValue
let name = prefs["name"].stringValue
let child = prefs["children"].arrayValue[0].arrayValue[3]
您可以轻松构建自己的JSON结构,并使用Alamofire发送:
好吧,(抱歉没有深入分析)首先,我要修改您的JSON,使其不包含动态元素的字典(三星有键3等等,它应该是数组,有意义吗?)
我提出了更好的JSON结构:
{
"preferences":[
{
"items":[
{
"id" : "3",
"name" : "Samsung"
},
{
"id" : "3",
"name" : "Nokia"
}
],
"id":"1",
"name":"Mobiles"
},
{
"items":[
{
"id" : "3",
"name" : "Nokia"
}
],
"id":"2",
"name":"Electronics"
}
]
}
现在使用JSONModel
将其映射到对象非常容易,您只需要关心映射键
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);
型号:
有点像全局参考,根模型,万一你决定添加一些额外的东西
#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.h”
@接口GlobalPreferences:JSONModel
@属性(非原子,强)NSArray*首选项;//在这里使用协议可以指定应该映射到哪个模型数据
@属性(非原子,强)NSArray*somethingElse;//其他一些设置可能在这里
@结束
#导入“GlobalPreferences.h”
@实现全局参考
@结束
偏好
#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.h”
@协议偏好
@结束
@接口首选项:JSONModel
@属性(非原子,强)NSNumber*ID;//必修的
@属性(非原子,强)NSString*name;//必修的
@属性(非原子、强)NSArray*项;
@结束
#导入“Preference.h”
@实施偏好
#pragma标记-JSONModel
+(JSONKeyMapper*)键映射器{
返回[[JSONKeyMapper alloc]initWithDictionary:@{
@“id”:@“id”,
}];
}
@结束
首选项
#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
#导入
//这个协议只是为了让JSONModel知道在数组/字典的情况下需要将数据解析到哪个模型
@协议优先项
@结束
@接口首选项:JSONModel
@属性(非原子,强)NSNumber*ID;
@属性(非原子,强)NSString*名称;
@结束
#导入“PreferenceItem.h”
@实施优先项目
#pragma标记-JSONModel
+(JSONKeyMapper*)键映射器{
返回[[JSONKeyMapper alloc]initWithDictionary:@{
@“id”:@“id”,
}];
}
@结束
对于coreData
,应该可以
也许对于您来说,所有这些都不是必需的,但是在解析/映射网络响应时,您需要注意很多事情,例如数据类型数据类型,缺少键,错误处理等等。如果你手动映射,你有可能有一天会破坏应用程序。了解其他人的做法,例如你的问题有答案。@Injectios你有什么建议,我可以将上面的JSON响应转换为JSONModel吗?我知道JSONModel,但我不知道这个响应如何与此兼容?@user3182143很抱歉,我没有理解你的意思?你能推荐显示标准JSON格式的适当和可靠的源代码吗?因为我认为这不是好的JSON响应格式。是的,你可以使用JSONModel转换任何类型的响应和嵌套元素,你只需要关心一件事就是映射键(我将尝试编写示例)谢谢你的回答,但目前我能得到的最好方法是什么?谢谢你详细的回答。你的意思是没有“items”:[{“id”:“3”,“name”:“Nokia”}],这种键(例如:id)在响应时很难解析?我的后台人员认为他们是专家,不喜欢更改JSON格式。我仍然可以使用他们对JSON模型的响应吗?我该如何向他们解释D(也就是说,为什么要求任何可靠的来源来说明其他专家在做什么)我想,简单地说,数据库中的值不应该是集合(字典等)的键,否则你如何将它映射到你的模型?您需要创建属性来通过这些键解析json,对吗?您不知道这些值,而是知道数据库中的字段(id、名称等)。如果您使用它们的JSON,您就无法拥有自定义模型,您只需将NSDictionary作为一个模型对象简单地使用,就像您已经做过的一样。或者你需要手动映射它,比如model.id=dictionary.key等等。我想这不是做API的正确方法,请检查f.e
#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