iOS 中使用 KVC 对 Json 的解析 <一>

APP端经常需要与服务器交互,json格式的数据是经常被使用的,解析json是经常要做的一件事。

先看一个示例,一般情况下,我们是这么解析的:

//  main.m
//  Demo
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Box.h"
int main(int argc, const char * argv[]) {
    /**
     *  {
     *      "name":"Mr.Li",
     *      "number":"007",
     *      "box": {
     *          "pen":"Hero",
     *          "phone":"iPhone 10"
     *          "pad":"iPad Air"
     *      }
     *  }
     */
    NSString *jsonString = @"{"name":"Mr.Li",
                              "number":"007",
                              "box":{
                                "pen":"Hero",
                                "phone":"iPhone 10",
                                "pad":"iPad Air"
                              }
                            }";

    NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];

    NSError *error = nil;
    NSDictionary *jsonDic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&error];
    Person *person = [[Person alloc] init];
    [person setName:jsonDic[@"name"]];
    [person setNumber:jsonDic[@"number"]];
    NSDictionary *boxDic = jsonDic[@"box"];
    Box *box = [[Box alloc] init];
    [box setPen:boxDic[@"pen"]];
    [box setPhone:boxDic[@"phone"]];
    [box setPad:boxDic[@"pad"]];
    person.myBox = box;
    NSLog(@"%@",person);
    retun 0;
?}

Person 类(略去Person.m,仅仅重写了description方法):

//  Person.h
//  Demo
#import <Foundation/Foundation.h>
#import "Box.h"
@interface Person : NSObject
@property (copy,nonatomic) NSString *name;
@property (copy,nonatomic) NSString *number;
@property (strong,nonatomic) Box *myBox;
@end

Box 类 (略去Box.m,仅仅重写了description方法):

//  Box.h
//  Demo
#import <Foundation/Foundation.h>
@interface Box : NSObject
@property (copy,nonatomic) NSString *pen;
@property (copy,nonatomic) NSString *phone;
@property (copy,nonatomic) NSString *pad;
@end

关键是这样的,当APP端有大量数据需要与服务器进行交互的时候,这么一条一条解析绝笔是相当累的(纯体力活)。

作为一个有理想的码农,就得想一个比较好的办法。

———— 秘诀:KVC ————

什么是KVC?即Key-Value Coding。简单来说,就是通过一个字符串key来设置该key对应属性的值。

举个简单的例子:

    [person setValue:@"Mr.Zhang" forKey:@"name"];
    NSLog(@"name:%@",person.name);

    /**
     * 运行结果:
     * name:Mr.Zhang
     */

KVC的实现原理就是反射,通过@"name"这个字符串映射出对应的属性然后进行修改。

在Persion.m中添加parsingDataFromDictionary:方法

- (void)parsingDataFromDictionary:(NSDictionary *)parameters {
    for (NSString *key in parameters) {
        id value = parameters[key];
        if (value != [NSNull null] && value != nil){
            [self setValue:parameters[key] forKey:key];
        } else {
            [self setValue:[NSNull null] forKey:key];
        }
    }
}

这样运行起来会有问题,就是当key为box时候,会导致程序出错

有两种方案解决这个问题

解决之前,先在Box.m 中实现parsingDataFromDictionary:方法,(其实方法体完全一样的,这里暂且那么写,后面会讲到可以进行封装起来),备用

第一种:

修改parsingDataFromDictionary:方法(黑体字为新增代码),

for (NSString *key in parameters) {
        id value = parameters[key];
        NSError *error = nil;
        if([self validateValue:&value forKey:key error:&error]){
            if (value != [NSNull null] && value != nil){
                [self setValue:parameters[key] forKey:key];
            } else {
                [self setValue:[NSNull null] forKey:key];
            }
        }
    }

在Person.m中增加validateName:error:方法(Name为<key>,key的首字母大写)

- (BOOL)validateBox:(id *)ioValue error:(NSError *__autoreleasing *)error {
    if ([*ioValue isKindOfClass:[NSDictionary class]]) {
        Box *box = [[Box alloc]initWithDictionary:*ioValue];
        *ioValue = box;
    }
    return YES;
}

<!!!  注意:是validateName:error:方法,而不是重写validateValue:forKey:error:  !!!>

第二种:

在Person.m中,增加setValue:forUndefinedKey:方法,

- (void)setValue:(id)value forUndefinedKey:(NSString *)key {
    NSLog(@"未定义的Key:%@, value:%@",key,value);
    if ([key isEqualToString:@"box"] && [value isKindOfClass:[NSDictionary class]]) {
        Box *box = [[Box alloc] initWithDictionary:value];
        self.myBox = box;
    }
}

总得来说,第一种方案是在赋值之前进行检测并订正,第二种方案则是赋值失败之后,再进行订正。

以上两种解决方案都可以,看似第一种麻烦一些,但是就比如当Person.Box的实例也叫box的时候,第二种方法是解决不了的,会导致直接将box字典,强制赋值给person.box,此时第一种方案则比较方便。

时间: 2024-08-25 01:22:36

iOS 中使用 KVC 对 Json 的解析 <一>的相关文章

iOS平台基于KVC的JSON与数据对象绑定

iOS平台基于KVC的JSON与数据对象绑定 作者:chszs,未经博主允许不得转载.经许可的转载需注明作者和博客主页:http://blog.csdn.net/chszs 在iOS平台上,要操纵JSON数据并不困难,但是,我们还有更简单的解决方案,使用KVC,全称是Key-Value Coding. 假设开发者(你)开发了一款应用,它的数据来自于外部对Web服务,要从Web服务中取回一些JSON数据,数据如下: {"count": 3, "sum": 9.0, &

【IOS开发之Objective-C】Json的解析 一

一.什么是Json? 关于Json的解释还是看百度百科是怎么解释的<百度百科---JSON>,这里还是比较专业的.首先我们已经知道了我们对象是什么也知道一些它的基本格式(百度百科有说明). 我们也来看看我保存在本地的一个Json文件,来具体分析一下它的格式. 先选择左上角的"Outline"模式,我们看见从左到右就是这么三列,分别是"Type"---类型,"Value"---值和"Name"---名字.有的&quo

iOS狂暴之路---iOS中应用的数据存储方式解析

一.前言 前面一篇文章中已经介绍了iOS应用中的视图控制器知识点,而本文不会按照常理来介绍View的知识点,而是先介绍iOS中的数据存储知识点,因为关于View的知识点太多了,后面会连续详细介绍一下.这篇先来看一下iOS中的数据存储功能分析.每一个iOS应用和Android应用一样,都有其对应的沙盒存储自己的数据,但是iOS和Android有一个区别就在于没有SD卡的概念了,也就说在iOS中应用的数据只能保存到自己的沙盒中.这也可以看出来iOS为了应用的安全考虑. 在开发Android的时候都知

IOS中关于KVC与KVO知识点

一.简介 KVC/KVO是观察者模式的一种实现,在Cocoa中是以被万物之源NSObject类实现的NSKeyValueCoding/NSKeyValueObserving非正式协议的形式被定义为基础框架的一部分.从协议的角度来说,KVC/KVO本质上是定义了一套让我们去遵守和实现的方法.当然,KVC/KVO实现的根本是Objective-C的动态性和runtime,这在后文的原理部分会有详述.另外,KVC/KVO机制离不开访问器方法的实现. 1.KVC简介 全称是Key-value codin

IOS中Json解析的四种方法

作为一种轻量级的数据交换格式,json正在逐步取代xml,成为网络数据的通用格式. 有的json代码格式比较混乱,可以使用此“http://www.bejson.com/”网站来进行JSON格式化校验(点击打开链接).此网站不仅可以检测Json代码中的错误,而且可以以视图形式显示json中的数据内容,很是方便. 从IOS5开始,APPLE提供了对json的原生支持(NSJSONSerialization),但是为了兼容以前的ios版本,可以使用第三方库来解析Json. 本文将介绍TouchJso

ios中json解析出现的null问题

在iOS开发过程中经常需要与服务器进行数据通讯,Json就是一种常用的高效简洁的数据格式. 问题现象 但是几个项目下来一直遇到一个坑爹的问题,程序在获取某些数据之后莫名崩溃.其实很早就发现了原因:由于服务器的数据库中有些字段为空,然后以Json形式返回给客户端时就会出现这样的数据: "somevalue":null 通过JsonKit 这个第三方库解析出来的数据就成了 somevalue = "<null>"; 这个数据类型不是nil 也不是 Strin

iOS 中json解析数据出现中文乱码的问题

一般服务器的编码格式都是UTF8,这样通过json解析下来的的数据,一般中文是不会出现乱码,但是如果服务器的编码格式不是UTF8,通过json解析的数据中的中文容易出现luan乱码,怎么解决这个问题呢? 一般都是通过转码来解决,但是直接转码,是不能达到效果的,例如 [jsonStringstringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding] 这样直接转码是达不到效果的. 解析数据的时候,可以先把数据存放在NSdata对象中,

iOS中JSON解析和XML解析的区别

iOS中网络传输的格式可粗略的分为XML和JSON两种,具体的传输方式又可分为GET和POST. 其中XML格式是最早出现的,但是由于复杂,并且占用字节数相对较大,故不太适合移动端,后来简化为JSON格式. JSON本身的数据结构只有字典和数组两种,在IOS5以后出现了原生解析,而之前则有SBJson和JsonKit第三方库解析. SBJson和JsonKit的特点: 1.第三方库解析SBJson是所有解析效率里面最低的,之所以能够广泛普及,是因为其简单,封装的低耦合性,可以快速抽离出一个类,在

【转】IOS中Json解析的四种方法

原文网址:http://blog.csdn.net/enuola/article/details/7903632 作为一种轻量级的数据交换格式,json正在逐步取代xml,成为网络数据的通用格式. 有的json代码格式比较混乱,可以使用此“http://www.bejson.com/”网站来进行JSON格式化校验(点击打开链接).此网站不仅可以检测Json代码中的错误,而且可以以视图形式显示json中的数据内容,很是方便. 从IOS5开始,APPLE提供了对json的原生支持(NSJSONSer