DCKeyValueObjectMapping 1.5

DCKeyValueObjectMapping 1.5

测试已测试
语言语言 Obj-CObjective C
许可证 MIT
发布最新发布2015年9月

Diego Chohfi 维护。



  • 作者
  • Diego Chohfi

简介

KeyValueObjectMapping 是一个 Cocoa 框架,它提供了一个简单的方法来处理任何键/值类型,例如 JSONXMLplist,甚至是常见的 NSDictionary。无需额外的框架。

它旨在与解析器一起使用,例如:NSJSONSerializationJSONKitNSXMLParser 和其他资源,主要目标是避免在处理键/值类型时需要进行的繁琐工作。

功能

  • 将任何类型的键/值类型转换为所需的对象。可以是 JSONXMLplist 或简单的 NSDictionary
  • 不要生成所有属性的访问器,保持您的属性 只读,框架将自动将值放置在对象上。
  • 基于约定而非配置
    1. 如果您的属性与 NSDictionary 上的键同名,一切都将自动完成。
    2. 如果源中的键之间由某些字符分隔,您可以配置该字符是什么,并且框架将根据该字符分割并将其转换为驼峰形式以找到适当的属性。
  • 通过 进行自定义,在创建实例或解析值时更改默认行为。使用 DCCustomInitializeDCCustomParser
  • 使用 DCObjectMapping 将任何键映射到不遵守约定的特定属性。
  • 要映射 一对一 关系,使用 DCArrayMapping 来告知将要插入的具体元素类型。
  • 使用 DCPropertyAggregator 将值聚合到特定属性。
  • 使用特定的日期模式(通过配置传递)解析 NSDate 或如果它是以毫秒形式(自1970年1月1日起的UNIX 时间戳)在 JSON 中发送的,则无需额外配置即可进行解析。
  • 如果有一个指向 NSURL 的属性,则框架将尝试使用 [NSURL URLWithString:] 方法将值作为 NSString 传递。

安装

  • 使用 CocoaPods,这是在 Objective-C 世界中管理依赖项的最简单方法。

  • 使用 iOS-Universal-Framework 由于 KeyValueObjectMapping 使用 iOS-Universal-Framework 来构建和编译项目,您可以轻松地将 iOS-Universal-Framework 生成的 .framework 拖入您的应用程序中,导入头文件 DCKeyValueObjectMapping.h 并开始使用该框架。

    • 必需的导入
        #import <KeyValueObjectMapping/DCKeyValueObjectMapping.h>

用法

KeyValueObjectMapping 是一个简单的对象,您需要做的就是创建一个新的对象,然后将一个字典转换为任何类。

假设您有一些像这样的 JSON

{
    "id_str": "27924446",
    "name": "Diego Chohfi",
    "screen_name": "dchohfi",
    "location": "São Paulo",
    "description": "Instrutor na @Caelum, desenvolvedor de coração, apaixonado por música e cerveja, sempre cerveja.",
    "url": "http://about.me/dchohfi",
    "protected": false,
    "created_at": "Tue Mar 31 18:01:12 +0000 2009"
}

您的 User 模型看起来像这样

@interface User : NSObject
@property(nonatomic, strong) NSString *idStr;
@property(nonatomic, strong) NSString *name;
@property(nonatomic, strong) NSString *screenName;
@property(nonatomic, strong) NSString *location;
@property(nonatomic, strong) NSString *description;
@property(nonatomic, strong) NSURL *url;
@property(nonatomic, strong) BOOL protected;
@property(nonatomic, strong) NSNumber *followersCount;
@property(nonatomic, strong) NSDate *createdAt;
@end

使用任何 JSON 解析器,您需要将这个 NSString 转换为 NSDictionary 表示形式

NSError *error;
NSDictionary *jsonParsed = [NSJSONSerialization JSONObjectWithData:jsonData
                                  options:NSJSONReadingMutableContainers error:&error];

如果您不使用 KeyValueObjectMapping,则需要创建一个 User 类型的实例,并在字典上设置与属性名称相同的所有属性。并在需要时将其转换。

User *user = [[User alloc] init];
[user setIdStr: [jsonParsed objectForKey: @"id_str"]];
[user setName: [jsonParsed objectForKey: @"name"]];
[user setScreenName: [jsonParsed objectForKey: @"screen_name"]];

NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.datePattern = @"eee MMM dd HH:mm:ss ZZZZ yyyy";
NSDate *date = [formatter dateFromString:@"Sat Apr 14 00:20:07 +0000 2012"];

[user setCreatedAt: date];

枯燥的工作,不是吗?所以,如果您使用 KeyValueObjectMapping,您只需要提供字典和要创建的类,其余的都将自动完成。

DCKeyValueObjectMapping *parser = [DCKeyValueObjectMapping mapperForClass: [Tweet class]];

Tweet *tweet = [parser parseDictionary:jsonParsed];
NSLog(@"%@ - %@", tweet.idStr, tweet.name);

DCParserConfiguration

如果您的 NSDate 模式与默认模式不同,默认模式为 @"eee MMM dd HH:mm:ss ZZZZ yyyy",则可以配置为使用不同的模式。因此,有一个对象可以向框架添加自定义配置。

使用 DCParserConfiguration,可以更改某些组件的默认行为,例如解析日期的默认模式。

DCParserConfiguration *config = [DCParserConfiguration configuration];
config.datePattern = @"dd/MM/yyyy";

DCKeyValueObjectMapping *parser = [DCKeyValueObjectMapping mapperForClass: [Tweet class] andConfiguration: config];

覆盖属性名称

如果您的 JSON 有一些特定的键不匹配属性名称,则可以使用 DCObjectMapping 将此键映射到属性,属性类型也可以是特定的对象。

您的 Tweet 模型

@interface Tweet : NSObject
@property(nonatomic, readonly) NSString *idStr;
@property(nonatomic, readonly) NSString *tweetText;

@property(nonatomic, readonly) User *userOwner;

@end

并且收到的 JSON 符合以下结构

{
    "id_str": 190957570511478800,
    "text": "Tweet text",
    "user": {
        "name": "Diego Chohfi",
        "screen_name": "dchohfi",
        "location": "São Paulo"
    }
}

使用 DCObjectMapping,可以解析这个 JSON 并像这样覆盖键名

DCParserConfiguration *config = [DCParserConfiguration configuration];

DCObjectMapping *textToTweetText = [DCObjectMapping mapKeyPath:@"text" toAttribute:@"tweetText" onClass:[Tweet class]];
DCObjectMapping *userToUserOwner = [DCObjectMapping mapKeyPath:@"user" toAttribute:@"userOwner" onClass:[Tweet class]];

[config addObjectMapping:textToTweetText];
[config addObjectMapping:userToUserOwner];

DCKeyValueObjectMapping *parser = [DCKeyValueObjectMapping mapperForClass: [Tweet class]  andConfiguration:config];
Tweet *tweetParsed = [parser parseDictionary:json];

解析 NSArray 属性

由于Objective-C不支持像Java和其他静态语言那样的类型化集合,我们无法确定集合中元素的类型。但是,可以配置键值对象映射(KeyValueObjectMapping),以便了解将在类的特定属性中添加到集合的元素类型。

因此,如果模型User有许多推文

@interface User : NSObject
@property(nonatomic, strong) NSString *idStr;
@property(nonatomic, strong) NSString *name;
@property(nonatomic, strong) NSString *screenName;
@property(nonatomic, strong) NSString *location;
@property(nonatomic, strong) NSString *description;
@property(nonatomic, strong) NSURL *url;
@property(nonatomic, strong) BOOL protected;
@property(nonatomic, strong) NSNumber *followersCount;
@property(nonatomic, strong) NSDate *createdAt;

@property(nonatomic, strong) NSArray *tweets;

@end

那么推文看起来是

@interface Tweet : NSObject
@property(nonatomic, strong) NSString *idStr;
@property(nonatomic, strong) NSString *text;
@property(nonatomic, strong) NSDate *createdAt;

@end

并且JSON看起来是

{
    "id_str": "27924446",
    "name": "Diego Chohfi",
    "screen_name": "dchohfi",
    "location": "São Paulo",
    "description": "Instrutor na @Caelum, desenvolvedor de coração, apaixonado por música e cerveja, sempre cerveja.",
    "url": "http://about.me/dchohfi",
    "protected": false,
    "created_at": "Tue Mar 31 18:01:12 +0000 2009",
        "tweets" : [
            {
                "created_at" : "Sat Apr 14 00:20:07 +0000 2012",
                "id_str" : 190957570511478784,
                "text" : "Tweet text"
            },
            {
                "created_at" : "Sat Apr 14 00:20:07 +0000 2012",
                "id_str" : 190957570511478784,
                "text" : "Tweet text"
            }
        ]
}

使用DCArrayMapping并将其添加到配置中,您就可以告诉KeyValueObjectMapping如何解析特定的属性。

DCArrayMapping *mapper = [DCArrayMapping mapperForClassElements: :[Tweet class] forAttribute:@"tweets"] onClass:[User class]];

DCParserConfiguration *config = [DCParserConfiguration configuration];
[config addArrayMapper:mapper];

DCKeyValueObjectMapping *parser = [[DCKeyValueObjectMapping mapperForClass:[User class]  andConfiguration:configuration];
User *user = [parser parseDictionary:jsonParsed];

将值聚合到特定类型

有时你面临的解析JSON没有权限修改结构体,并且你不想使你的类遵循特定的结构体。使用DCPropertyAggregator,你可以将一个键值聚合到你的领域模型的特定属性上。

因此,如果你的JSON看起来像这样

{
    "tweet" : "Some text",
    "latitude" : -23.588453,
    "longitude" : -46.632103,
    "distance" : 100
}

如果你遵循这个JSON结构,你的对象不会那么有组织,对吗?所以,你可以使你的对象遵循不同的结构

@interface Tweet : NSObject
@property(nonatomic, readonly) NSString *text;
@property(nonatomic, readonly) Location *location;
@end

@interface Location : NSObject
@property(nonatomic, readonly) NSNumber *distance;
@property(nonatomic, readonly) Point *point;
@end

@interface Point : NSObject
@property(nonatomic, readonly) NSNumber *latitude;
@property(nonatomic, readonly) NSNumber *longitude;
@end

并且使用DCPropertyAggregator来映射这个特定的行为

DCPropertyAggregator *aggregteLatLong = [DCPropertyAggregator aggregateKeys:[NSSet setWithObjects:@"latitude", @"longitude", nil] intoAttribute:@"point"];
DCPropertyAggregator *aggregatePointDist = [DCPropertyAggregator aggregateKeys:[NSSet setWithObjects:@"point", @"distance", nil] intoAttribute:@"location"];

DCParserConfiguration *configuration = [DCParserConfiguration configuration];
[configuration addAggregator:aggregteLatLong];
[configuration addAggregator:aggregatePointDist];

DCKeyValueObjectMapping *parser = [DCKeyValueObjectMapping mapperForClass:[Tweet class] andConfiguration:configuration];
Tweet *tweet = [parser parseDictionary: json];

Bitdeli Badge