Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios Objective-c中更好的JSON解析实现和最佳实践?_Ios_Json_Web Services_Parsing - Fatal编程技术网

Ios Objective-c中更好的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; }; }; 这是我的

我收到以下JSON响应,用于在核心数据中保存用户首选项

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]);
        }
    }
我有三个问题

  • 如何改进我的代码片段?有没有更短的方法来实现这一点

  • 这个JSON响应对于移动端解析足够好吗?它是好的JSON格式吗?作为移动开发人员,在使用核心数据方面,我们是否应该遵循任何JSON响应格式(这只是将DB实现简化为最佳实践)

  • 如何从Objective-c中再次构造类似这样的JSON字符串


  • 我知道您询问了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