JSON

什么是JSON

  • JSON是一种轻量级的数据格式,一般用于数据交互
  • 服务器返回给客户端的数据,一般都是JSON格式或者XML格式(文件下载除外)

  • JSON的格式很像OC中的字典和数组

    {"name" : "jack", "age" : 10}
    {"names" : ["jack", "rose", "jim"]}
    标准JSON格式的注意点:key必须用双引号
    
  • 要想从JSON中挖掘出具体数据,得对JSON进行解析
    • JSON 转换为 OC数据类型

JSON – OC 转换对照表

JSON – OC 转换对照表

JSON解析方案

JSON

  • 在iOS中,JSON的常见解析方案有4种

    • 第三方框架:JSONKit、SBJson、TouchJSON(性能从左到右,越差)
    • 苹果原生(自带):NSJSONSerialization(性能最好)
  • NSJSONSerialization的常见方法

    • JSON数据 -> OC对象
      // options:参数一般没kNilOptions,效率最高
      +(id)JSONObjectWithData:(NSData *)data options:(NSJSONReadingOptions)opt error:(NSError **)error;
      
  • NSJSONReadingOptions

    • NSJSONReadingMutableContainers = (1UL << 0)
       创建出来的数组和字典就是可变
      
    • NSJSONReadingMutableLeaves = (1UL << 1)
       数组或者字典里面的字符串是可变的
      
    • NSJSONReadingAllowFragments

       允许解析出来的对象不是字典或者数组,比如直接是字符串或者NSNumber
      
    • OC对象 -> JSON数据

      // options:参数一般没kNilOptions,效率最高
      +(NSData *)dataWithJSONObject:(id)obj options:(NSJSONWritingOptions)opt error:(NSError **)error;
      

json数据转换成OC对象


{} -> NSDictionary @{}
[] -> NSArray @[]
"jack" -> NSString @"jack"
10 -> NSNumber @10
10.5 -> NSNumber @10.5
true -> NSNumber @1
false -> NSNumber @0
null -> NSNull

字典转模型框架

  • Mantle
    所有模型都必须继承自MTModel
    
  • JSONModel
    所有模型都必须继承自JSONModel
    
  • MJExtension
    不需要强制继承任何其他类
    

解析JSON

        NSString * path = [[NSBundle mainBundle] pathForResource:@"help" ofType:nil];

        NSData * data = [NSData dataWithContentsOfFile:path];
        // 解析JSON
        NSArray * dictArr = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];

KVC 解析字典

使用KVC 解析字典配合JSON

事例

JXHtmlItem.h

#import <Foundation/Foundation.h>

@interface JXHtmlItem : NSObject
/** 标题 */
@property (nonatomic,strong) NSString * title;
/** HTML */
@property (nonatomic,strong) NSString * html;
/** ID */
@property (nonatomic,strong) NSString * ID;

+ (instancetype)htmlItemWithDict:(NSDictionary *)dict;
@end

JXHtmlItem.m

#import "JXHtmlItem.h"

@implementation JXHtmlItem
+ (instancetype)htmlItemWithDict:(NSDictionary *)dict {
    JXHtmlItem * html = [[self alloc] init];

    [html setValuesForKeysWithDictionary:dict];
    // 遍历字典中所有KEY
    return html;
}

- (void)setValue:(id)value forUndefinedKey:(NSString *)key {
    if ([key isEqualToString:@"id"]) {
        [self setValue:value forKeyPath:@"ID"];
    } else {
        [super setValue:value forKey:key];
    }
}

@end

JXBaseViewController.h

#import "JXBaseViewController.h"

@interface JXHelpController : JXBaseViewController

@end

JXHelpController.m

#import "JXHelpController.h"
#import "JXHtmlItem.h"

@interface JXHelpController ()
/** 保存数组 */
@property (nonatomic,strong) NSMutableArray * items;
@end

@implementation JXHelpController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self setup];
}

- (void)setup {
    [self items];
}

- (NSMutableArray *)items {
    if (_items == nil) {
        _items = [NSMutableArray array];

        NSString * path = [[NSBundle mainBundle] pathForResource:@"help.json" ofType:nil];

        NSData * data = [NSData dataWithContentsOfFile:path];
        // 解析JSON
        NSArray * dictArr = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];

        for (NSDictionary * dict in dictArr) {
            JXHtmlItem * html = [JXHtmlItem htmlItemWithDict:dict];
            [_items addObject:html];
        }

    }
    return _items;
}
@end

使用运行时来解析

需要新建一个分类

NSObject+JXModel.h


#import <Foundation/Foundation.h>

@interface NSObject (JXModel)


// 快速进行字典转模型
// mapDict:模型中的哪个属性名跟字典里面的key对应
+ (instancetype)objcWithDict:(NSDictionary *)dict mapDict:(NSDictionary *)mapDict;

@end

NSObject+JXModel.m

#import "NSObject+JXModel.h"
#import <objc/runtime.h>

@implementation NSObject (JXModel)

+ (instancetype)objcWithDict:(NSDictionary *)dict mapDict:(NSDictionary *)mapDict
{
    id objc = [[self alloc] init];


    // 遍历模型中属性
    unsigned int count = 0;
    Ivar *ivars = class_copyIvarList(self, &count);

    for (int i = 0 ; i < count; i++) {
        Ivar ivar = ivars[i];

        // 属性名称
        NSString *ivarName = @(ivar_getName(ivar));


        ivarName = [ivarName substringFromIndex:1];

        id value = dict[ivarName];
        // 需要由外界通知内部,模型中属性名对应字典里面的哪个key
        // ID -> id
        if (value == nil) {
            if (mapDict) {
                NSString *keyName = mapDict[ivarName];

                value = dict[keyName];
            }
        }


        [objc setValue:value forKeyPath:ivarName];


    }


    return objc;
}

@end

使用方法

在解析模型类中使用


#import "JXHtmlItem.h"
#import "NSObject+JXModel.h"

@implementation JXHtmlItem
+ (instancetype)htmlItemWithDict:(NSDictionary *)dict {

    JXHtmlItem * html = [JXHtmlItem objcWithDict:dict mapDict:@{@"ID":@"id"}];

//    [html setValuesForKeysWithDictionary:dict];
    // 遍历字典中所有KEY
    return html;
}

results matching ""

    No results matching ""