RestGoatee-Core 2.5.5

RestGoatee-Core 2.5.5

测试已测试
Lang语言 Obj-CObjective C
许可证 BSD
发布最后发布2016年9月
SPM支持 SPM

Ryan Dignard 维护。



  • Ryan Dignard

RestGoatee-Core 是一个框架,它将原始的 NSDictionaryNSXMLParser 对象转换成您的领域模型。

支持:iOS 5.0, OS X 10.7, watchOS 1.0, tvOS 9.0;需要 ARC

这个库的目标是在一般情况下保持简单并通过扩展来适应。
1) 将数据源转换为领域模型的行为不应该包含业务逻辑或关键转换。
2) API 层应该能够无缝地处理新对象和对象属性,而不需要新的反序列化逻辑。示例项目中这个 提交 添加了一个全新的响应对象而没有引起波澜。
3) 由于 JSON 和 XML 类型有限,反序列化器需要能够智能地映射到一个更广泛的标准类型族。
4) 通常在项目初期不考虑 CoreData 支持;这个库使得以最少的重构开启它更为简单。CoreData 支持是隐含的,但在没有它的项目中是不活跃的。
5) 默认映射行为应该既直观(99% 的时间正确)又可扩展。
6) 在复杂性和代码行数方面,默认应该是最简洁的。您无需为一对一、命名良好且显式类型化的对象或属性指定映射。

为什么使用 RestGoatee?

考虑您最喜欢的或最受欢迎的模型框架

  • 它是否需要映射来构建简单的对象?
  • 它是否支持 NSManagedObject 子类?
  • 它是否理解键 foo-bar foo_barfooBar 很可能表示同一个键?
  • JSON 或 XML?

安装

  • 对于Cocoapods用户,将pod 'RestGoatee-Core'添加到您的Podfile中,并运行pod install
  • 对于Carthage用户,添加github "rdignard08/RestGoatee-Core" "master"(您也可以通过指定release标签代替master)。
  • 对于手动安装,请将顶级文件夹"RestGoatee-Core"包含在您的仓库中(所有内容都是前缀)。
    • 包含#import "RestGoatee-Core.h"以包含所有公共头文件并开始使用库。

示例

让我们探讨如何使用给定的域模型
@interface BaseObject : NSObject
@property (nonatomic, strong) NSString* stringValue;
@property (nonatomic, strong) NSNumber* numberValue;
@property (nonatomic, assign) double doubleValue;
@end

@interface DerivedObject : BaseObject
@property (nonatomic, strong) NSDate* dateValue;
@property (nonatomic, strong) id rawValue;
@end
入门,让我们创建一个DerivedObject的实例,该实例使用一个NSDictionary
DerivedObject* derived = [DerivedObject objectFromDataSource:@{
                                                             @"stringValue" : @"aString",
                                                             @"numberValue" : @3,
                                                             @"doubleValue" : @3.14,
                                                             @"dateValue" : @"2016-01-17T16:13:00-0800",
                                                             @"rawValue" : [NSNull null]
                                                             } inContext:nil];

assert([derived.stringValue isEqual:@"aString"]);
assert([derived.numberValue isEqual:@3]);
assert(derived.doubleValue == 3.14);
assert([derived.dateValue timeIntervalSince1970] == 1453075980.0);
assert(derived.rawValue == [NSNull null]);

创建一个对象就这么简单。默认支持的数据源包括NSDictionary(用于JSON)和RGXMLNode(用于XML),但该协议是公开的,您可以根据自己的需求创建自己的数据源。

如果没有指定所有属性怎么办?
DerivedObject* derived = [DerivedObject objectFromDataSource:@{ @"stringValue" : @"aString" } inContext:nil];

assert([derived.stringValue isEqual:@"aString"]);
assert(derived.numberValue == nil);
assert(derived.doubleValue == 0.0);

如果没有提供值,则保留默认值。同样,如果有未使用的键,它们将被忽略。

如果我的API返回NSNull或值怎么办?
DerivedObject* derived = [DerivedObject objectFromDataSource:@{ @"stringValue" : [NSNull null] } inContext:nil];

assert(derived.stringValue == nil);

规则非常简单,并保证您永远不会破坏类型系统(NSURL*属性将始终有NSURLnil)。

  • 如果提供的值与属性类型的类型相同或有子类型,则将其设置为该值。
    • 因此,类型为idNSObject*的属性将接收任何值。
  • 如果值可以转换为属性类型(例如NSNumber通过.stringValue转换为NSString),则将其设置为转换后的值。
    • 大多数规则都发生在这里
      • NSString / NSNumber映射到idNSObjectNSNumberNSURLNSDateClass和基本类型(intdoublechar等)。
      • RGXMLNode映射到NSDictionary,然后NSDictionary映射到NSDictionaryNSObject的子类等。
  • 否则,属性保持未设置状态,值被丢弃。您会在运行时收到警告。
  • 完整的规则集可以从NSObject+RGDeserializationSpec.m中的测试套件中推断。
如果我的API键是蛇形命名怎么办?
DerivedObject* derived = [DerivedObject objectFromDataSource:@{ @"string_value" : @"aString" } inContext:nil];

assert([derived.stringValue isEqual:@"aString"]);

不是驼峰式命名?没问题。隐式映射将处理所有键的大小写不敏感ASCII字母和数字匹配的情况。

如果我的API键真的不同怎么办?
@implementation DerivedObject

+ (NSDictionary*) overrideKeysForMapping {
    return @{ @"super_secret_str" : @"stringValue" };
}

@end

DerivedObject* derived = [DerivedObject objectFromDataSource:@{ @"super_secret_str" : @"aString" } inContext:nil];

assert([derived.stringValue isEqual:@"aString"]);

提供+overrideKeysForMapping使您能够根据属性名映射键。任何未指定的键将进行默认处理,因此您只需指定异常即可。

如果默认行为不满足我的需求怎么办?
@implementation DerivedObject

- (BOOL) shouldTransformValue:(id)value forProperty:(NSString*)propertyName {
    if ([propertyName isEqual:@"stringValue"]) {
        self.stringValue = [value description].uppercaseString;
        return NO;
    }
    return YES;
}

@end

DerivedObject* derived = [DerivedObject objectFromDataSource:@{ @"stringValue" : @"abcd" } inContext:nil];

assert([derived.stringValue isEqual:@"ABCD"]);

您可以为-shouldTransformValue:forProperty:设置一个覆盖,并在需要时直接返回NO

序列化是如何工作的?
DerivedObject* derived = [DerviedObject new];
derived.stringValue = @"aString";
derived.numberValue = @3;
derived.doubleValue = 3.0;
NSDictionary* dictionaryRepresentation = [derived dictionaryRepresentation];

assert([dictionaryRepresentation[@"stringValue"] isEqual:@"aString"]);
assert([dictionaryRepresentation[@"numberValue"] isEqual:@"3"]);
assert([dictionaryRepresentation[@"doubleValue"] isEqual:@"3"]);

-dictionaryRepresentation 返回一个字典,其中键是属性的名称,值是序列化该值的结果。类型为 NSString*NSURL*NSNumber* 或原生的属性将是一个 NSString* 类型的值。NSNull* 值保持不变。NSArray*NSDictionary* 和所有其他 NSObject* 子类都会通过应用相同的规则来输出它们的子对象。

有关示例,请参阅 https://github.com/rdignard08/RestGoatee

许可证

简化版 BSD (2-clause)