NSObject-ObjectMap 2.3.1

NSObject-ObjectMap 2.3.1

测试已测试
Lang语言 Obj-CObjective C
许可证 自定义
释放上次发布2014年12月

Matt YorkMatt YorkBen Gordon维护。



  • uacaps

NSObject+ObjectMap

这是一个 NSObject 的嵌入类别,使得从 JSON 或 XML(包括 SOAP)初始化自定义对象变得简单,并将这些对象反序列化为 JSON/XML。它仅需要一点设置——然后您就再也不必为每个自定义 NSObject 创建自己的序列化和初始化方法了。

版本 2.0

ScreenShot


设置

唯一的一步是将 NSObject+ObjectMap.{h,m} 添加到您的项目中。就是这样。


处理 JSON

创建您的对象

这一步需要了解返回的 JSON 将是什么样子。检查您的数据源,并创建与之一致的自定义 NSObject 类。例如,假设您的 JSON 返回如下

{
  Username : "Big Al",
  Password : "r0llt1d3",
    Color : "Crimson",
    Location : "Tuscaloosa, AL",
    Championships: 15
}

如果是这种情况,您将创建这样一个自定义 NSObject,它的属性与之匹配

@property (nonatomic, retain) NSString *Username;
@property (nonatomic, retain) NSString *Password;
@property (nonatomic, retain) NSString *Color;
@property (nonatomic, retain) NSString *Location;
@property (nonatomic, retain) NSNumber *Championships;

这个类的好处在于,它不仅限于基本的 Objective-C 类(如 NSString 和 NSNumber),还可以处理您创建的任何对象。让我们把前面的类定义称为 User——现在让我们创建一个具有 User 类对象属性的实例。

// JSON snippet
{
    Name : "Bryant-Denny",
    CreatedByUser : {
        Username : "Big Al",
        Password : "r0llt1d3",
        Color : "Crimson",
        Location : "Tuscaloosa, AL",
        Championships: 15
    }
}

// Place.h
@property (nonatomic, retain) NSString *Name;
@property (nonatomic, retain) User *CreatedByUser;

NSObject+ObjectMap 通过反序列化 JSON 并将 JSON 包中的各种键与您想要映射的对象的各种属性相匹配来工作。这种设计的一个限制是,您必须将属性命名为与返回的键完全相同,否则该属性在反序列化完成后将保持未初始化(nil)。

处理数组

不幸的是,在使用 JSON 时,您对封装在数组中的对象的类型一无所知。为了将 JSON 反序列化到 NSObject,还需要进行一个额外的设置步骤。如果您的自定义 NSObject 包含一个或多个 NSArray,您需要为该对象创建一个自定义的 init 方法(或者把以下代码包括在您已经创建的自定义 init 中)。这个方法创建了一个名为 propertyArrayMap 的 NSDictionary,其中的键/值对将属性名称(键)与其想要为 NSArray 包含的对象类型(值)相匹配。当对象从您的 JSON 数据包创建时,其正在处理该属性是 NSArray,它将检查这个字典来找出它需要在数组中创建哪种类型的对象。以下是一个配置示例:

// JSON snippet
{
    Name : "Billy",
    FavoriteColors : ["Red","Blue","Tangerine"],
    FavoritePeople : [{
        Name : "Jenny",
        FavoriteColors: [@"Orange","Black"],
        FavoritePeople: []
    },{
        Name : "Ben",
        FavoriteColors: ["Silver","Emerald","Aquamarine"],
        FavoritePeople: []
    }]
}


// Person.h
@property (nonatomic, retain) NSString *Name;
@property (nonatomic, retain) NSArray *FavoriteColors;
@property (nonatomic, retain) NSArray *FavoritePeople;


// Person.m
-(id)init {
    self = [super init];
    if (self) {
        [self setValue:@"NSString" forKeyPath:@"propertyArrayMap.FavoriteColors"];
        [self setValue:@"Person" forKeyPath:@"propertyArrayMap.FavoritePeople"];
    }
    return self;
}

在这个例子中,我们有一个表示 Person 的 JSON 字符串。这个人有一个名字和两个数组特性,FavoriteColors 和 FavoritePeople。FavoriteColors 是一个字符串数组,FavoritePeople 是 Person 对象的数组。如您所见,为 Person.m 中创建的定制 init 方法设置了 propertyArrayMap,以处理应包含的对象类型(在 setValue 中)及其对应的键(forKeyPath)。与其他提到的属性和键一样,请确保它们拼写正确,以便正确反序列化和对象创建。

从 JSON 到对象

此时,您应该已经创建了自定义的 NSObjects,并且从 webservice 返回了 JSON 数据,可以直接将其转换成这些对象。现在,简单部分来了。使用内置的 NSJSONSerialization 方法将 JSON 数据转换成 NSDictionary 或 NSArray,然后将这些传递到一个方法中,该方法会从这些数据返回您的自定义 NSObject。我们将使用前面提到的 Person JSON 片段来说明这一点。

// JSON snippet
{
    Name : "Billy",
    FavoriteColors : ["Red","Blue","Tangerine"],
    FavoritePeople : [{
        Name : "Jenny",
        FavoriteColors: [@"Orange","Black"],
        FavoritePeople: []
    },{
        Name : "Ben",
        FavoriteColors: ["Silver","Emerald","Aquamarine"],
        FavoritePeople: []
    }]
}

// Turn that JSON into an NSDictionary, then into your Person object
// - jsonData is the NSData equivalent of the JSON snippet above.
NSData *jsonData;

// Now to create the Person object
Person *newPerson = [[Person alloc] initWithJSONData:jsonData];

使用数组的方式几乎完全相同,但是在 JSON 反序列化返回的是 NSArray 而不是 NSDictionary。如果这个 NSArray 包含许多 Person 对象,请使用以下方法创建这个数组。

NSArray *peopleArray = [NSObject arrayOfType:[Person class] fromJSONData:jsonData];

将对象序列化为 JSON

大多数现代的 web 服务和 API 使用 JSON postfix 数据来传递可以在服务器端处理的对象。使用这个类创建您的 JSON 数据就像吸管吸水一样简单。

Person *newPerson = [[Person alloc] init];
NSData *jsonData = [newPerson JSONData];

要查看 JSON 数据包的字符串表示,请使用返回 NSString 而不是 NSData 的 [NSObject JSONString] 方法。您可以使用在线的验证工具(如 jsonlint.com)来确保这是一个有效的 JSON。

故障排除

由于前面列出的约束条件,以下是一些要检查和考虑的事项,如果类不像预期的那样工作:

  • 对象的属性名称必须与 JSON 中的相应键完全相同。
  • 您的 JSON 对象实际上是一个 NSDictionary(或 NSArray),并且在反序列化过程中没有出错。
  • 如果您的 NSObjects 包含 NSArray 特性,您已使用自定义 init 方法设置 propertyArrayMap 键/值,并且命名正确。
  • 您设置的 OMDateFormat/OMTimeZone 正确。

处理 XML(和 SOAP)

创建您的对象

这一步需要了解将返回的 XML 将是什么样子。检查您的数据源,并创建匹配这些的自定义 NSObject 类。例如,假设您返回的 XML 看起来像这样:

<MyObject>
    <Username>Big Al</Username>
    <Password>r0llt1d3</Password>
    <Color>Crimson</Color>
    <Location>Tuscaloosa, AL</Location>
    <Championships>15</Championships>
<MyObject>

如果是这种情况,您将创建一个名为 MyObject 的自定义 NSObject,其属性与这些相匹配。

@property (nonatomic, retain) NSString *Username;
@property (nonatomic, retain) NSString *Password;
@property (nonatomic, retain) NSString *Color;
@property (nonatomic, retain) NSString *Location;
@property (nonatomic, retain) NSNumber *Championships;

序列化和反序列化

就像 JSON 一样,XML 支持嵌套的复杂对象。也不需要指定数组类型,因此处理 XML 可以说是更简单。要将对象序列化为 XML,只需做以下操作:

MyObject *object = [[MyObject alloc] init];

//*** Fill in object properties with data here ***

NSData *xmlData = [object XMLData];

//*** Send data over web ***

从 XML 反序列化回对象同样简单。

// XML String of Object
NSString *xmlString = @"<MyObject>
    <Username>Big Al</Username>
    <Password>r0llt1d3</Password>
    <Color>Crimson</Color>
    <Location>Tuscaloosa, AL</Location>
    <Championships>15</Championships>
<MyObject>";

// XML Data
NSData *xmlData = [xmlString dataUsingEncoding:NSUTF8StringEncoding];

// Create MyObject
MyObject *customObject = [[MyObject alloc] initWithXMLData:xmlData];

关于SOAP的说明: 目前仅支持简单的、基于标签的SOAP。如有需要,将支持更复杂的空间命名和属性处理。如果您发现处理更复杂SOAP的出色方法,请随时提交pull request。


与NSDates一起工作

NSObject+ObjectMap.h文件中有两个# define 常量,表示NSDate反序列化的格式/时区信息。将这些常量与您获取的JSON/XML关联起来,以确保NSDateFormatter正确地创建NSDate对象。这些属性是:

  • OMDateFormat
  • OMTimeZone

演示

要查看NSObject+ObjectMap的实际效果,请检查顶层Demos文件夹中的我们的许多样本Xcode项目中的一个。Google Places演示展示了NSObject+ObjectMap对JSON的处理,而Weather演示则负责XML。在运行之前,请务必查看它们的README以了解任何设置工作。

screenshot screenshot


单元测试

我们有全新的单元测试套件以确保ObjectMap在对其进行任何更改后仍然有效。您可以通过在Tests文件夹下打开UnitTests.xcodeproj来运行它。只需按下键盘上的Cmd - U即可运行,并在屏幕上查看是否显示了“Tests Succeeded”。有时它会显示“Tests Failed”,但如果您查看每个TestCase类,您会看到每个方法旁边都有绿色或红色的钻石。绿色钻石表示成功,红色钻石表示失败。



许可

版权所有(c)2012阿拉巴马大学董事会所有权利保留。

允许以源代码和二进制形式重新分发和使用,无论是否修改,只要满足以下条件:

  1. 源代码的重新分发必须保留上述版权声明、本条件列表以及以下免责声明。
  2. 二进制形式的重新分发必须在文档和/或其他与分发一起提供的材料中复制上述版权声明、本条件列表以及以下免责声明。
  3. 未经具体事先书面许可,不得使用大学名称或贡献者的名称endorse或promote从本软件衍生出的产品。

本软件按“原样”提供,并且不考虑明示的保证或建议性保证,包括但不限于适销性和适用于特定用途的隐含保证。在任何情况下,版权所有者或贡献者不对因使用本软件而产生的任何直接、间接、意外、特殊、示范性或后果性损害(包括但不限于替代商品或服务的采购;使用、数据或利润的损失;或业务中断)承担责任,无论索赔是由于何种原因,基于何种责任理论,无论是基于合同、严格责任还是侵权(包括疏忽或其他),即使是已知存在此类损害的风险。