Objective中更好的JSON解析实现

我正在接收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]);
        }
    }

我有3个问题。

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

  • 这个JSON响应是否足够用于移动端解析? 它是不错的JSON格式? 在使用核心数据方面,是否有任何JSON响应格式作为移动开发人员应遵循(它们只是将数据库实现作为最佳实践减少)?

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


  • 好吧,(对不起,没有深入的分析)首先我要修改你的JSON不要包含动态元素的dictionary (samsung有关键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);
    

    楷模:

    Kinda GlobalPreference,根模型,以防万一你决定添加额外的东西

     #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
    

    偏爱

    #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
    

    对于coreData应该coreData

    也许对于你来说,所有这些都不是必须的,但是当你解析/映射网络响应(比如data typesmissing keyserror handling等等)时,你需要关心很多事情。 如果你手动映射 - 你有可能在某天破坏应用程序。


    我知道你问了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]
    

    https://github.com/SwiftyJSON/SwiftyJSON

    您可以轻松构建自己的JSON结构并使用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/48075.html

    上一篇: Better JSON parsing implementation in Objective

    下一篇: Using Custom Headers for Response Messages; Bad Practice?