SYNCPropertyMapper 5.2.0

SYNCPropertyMapper 5.2.0

测试已测试
语言语言 Obj-CObjective C
许可证 MIT
发布最新版本Nov 2016
SPM支持 SPM

Elvis Nuñez维护。





SYNCPropertyMapper利用您的Core Data模型来推断如何将您的JSON值映射到Core Data。它很简单,也很明显。为什么每个人都没有这样做呢?

目录

用JSON填充NSManagedObject

使用你提供的JSON后端映射你的Core Data对象从未如此简单。

驼峰式命名的JSON

{
  "firstName": "John",
  "lastName": "Hyperseed"
}
NSDictionary *values = [JSON valueForKey:@"user"];
[user hyp_fillWithDictionary:values];
let userJSON = JSON["user"]
user.hyp_fill(with: userJSON)

您的Core Data实体应与您的后端模型匹配。您的属性应与它们的JSON对应物匹配。例如,firstName映射到firstNameaddress映射到address

下划线命名法的JSON

{
  "first_name": "John",
  "last_name": "Hyperseed"
}
NSDictionary *values = [JSON valueForKey:@"user"];
[user hyp_fillWithDictionary:values];
let userJSON = JSON["user"]
user.hyp_fill(with: userJSON)

您的Core Data实体应与您的后端模型匹配,但在camelCase中。您的属性应与它们的JSON对应物匹配。例如,first_name映射到firstNameaddress映射到address

属性类型

字符串和数字

这很直接,应该如您所期望的那样工作。JSON字符串映射为NSString和double、float、ints等,映射为NSNumber。

日期

我们默认支持ISO 8601和Unix时间戳,因为这些是解析日期时最常用的格式。我们还有一种相当高效的方式来解析这些字符串,这克服了使用NSDateFormatter性能问题

NSDictionary *values = @{@"created_at" : @"2014-01-01T00:00:00+00:00",
                         @"updated_at" : @"2014-01-02",
                         @"published_at": @"1441843200"
                         @"number_of_attendes": @20};

[managedObject hyp_fillWithDictionary:values];

NSDate *createdAt = [managedObject valueForKey:@"createdAt"];
// ==> "2014-01-01 00:00:00 +00:00"

NSDate *updatedAt = [managedObject valueForKey:@"updatedAt"];
// ==> "2014-01-02 00:00:00 +00:00"

NSDate *publishedAt = [managedObject valueForKey:@"publishedAt"];
// ==> "2015-09-10 00:00:00 +00:00"

如果您的日期不符合ISO 8601规范,您也可以使用变压器属性来解析日期。首先将您的属性设置为Transformable,然后在示例中,将其名称设置为DateStringTransformer

transformable-attribute

您可以在DateStringTransformer中找到日期变换器的示例。

数组

在Core Data模型器上,首先将属性设置为Binary Data以进行数组映射。

screen shot 2015-04-02 at 11 10 11 pm

let values = ["hobbies" : ["football", "soccer", "code"]]
managedObject.hyp_fill(with: values)
let hobbies = NSKeyedUnarchiver.unarchiveObject(with: managedObject.hobbies) as! [String]
// ==> "football", "soccer", "code"

字典

在Core Data模型器上,首先将属性设置为Binary Data以进行字典映射。

screen shot 2015-04-02 at 11 10 11 pm

let values = ["expenses" : ["cake" : 12.50, "juice" : 0.50]]
managedObject.hyp_fill(with: values)
let expenses = NSKeyedUnarchiver.unarchiveObject(with: managedObject.expenses) as! [String: Any]
// ==> "cake" : 12.50, "juice" : 0.50

异常

这个规则有两个例外。

  • id应与remoteID匹配。
  • 预留属性的前缀应为entityName(例如,type变为userTypedescription变为userDescription等)。在JSON中它们不需要改变,例如,您可以用typedescription保持不变。预留属性的完整列表可以在这里找到。

自定义

Remote mapping documentation

  • 如果您想将Core Data标识符(键)属性与具有不同命名的JSON属性进行映射,您可以在用户信息框中添加hyper.remoteKey并输入您想要的映射值。

深度映射

{
  "id": 1,
  "name": "John Monad",
  "company": {
    "name": "IKEA"
  }
}

在这个例子中,如果您想避免为公司创建Core Data实体,您可以直接映射到公司的名称。通过将此添加到companyName字段的用户信息

hyper.remoteKey = company.name

处理不良API

有时REST API中的值不是您想要的形式,这导致您必须扩展模型类以包含转换为值的方法和/或属性。甚至可能需要预处理JSON才能使用SYNCPropertyMapper。幸运的是,大多数这种情况可以通过使用ValueTransformer来解决。

例如,在我的用户模型中,我不再得到这个:

{
  "name": "Bob Dylan"
}

我们的后端开发人员决定他更喜欢数组,所以我们得到这个:

{
  "name": [
    "Bob Dylan"
  ]
}

由于SYNCPropertyMapper期望一个值为Bob Dylanname,我们必须在将其传入Core Data之前预处理这个值。为此,我们将首先创建一个ValueTransformer的子类。

import Foundation

class BadAPIValueTransformer : ValueTransformer {
    override class func transformedValueClass() -> AnyClass {
        return String.self as! AnyClass
    }

    override class func allowsReverseTransformation() -> Bool {
        return true
    }

    // Used to transform before inserting into Core Data using `hyp_fill(with:)
    override func transformedValue(_ value: Any?) -> Any? {
        guard let valueToTransform = value as? Array<String> else {
            return value
        }

        return valueToTransform.first!
    }

    // Used to transform before exporting into JSON using `hyp_dictionary`
    override func reverseTransformedValue(_ value: Any?) -> Any? {
        guard let stringValue = value as? String else { return value }

        return [stringValue]
    }
}

然后,我们将在Core Data属性的用户键中添加另一个项。键为hyper.valueTransformer,值为BadAPIValueTransformer

value-transformer

然后在执行hyp_fill(with:]之前,我们将做到以下几点:

ValueTransformer.setValueTransformer(BadAPIValueTransformer(), forName: NSValueTransformerName(rawValue: "BadAPIValueTransformer"))

这样!然后您的名字将是Bob Dylan,恭喜您获得诺贝尔和平奖。

顺便说一下,这也一样有效!所以使用hyp_dictionary将返回["Bob Dylan"]

从NSManagedObject生成JSON表示

UserManagedObject *user;
[user setValue:@"John" forKey:@"firstName"];
[user setValue:@"Hyperseed" forKey:@"lastName"];

NSDictionary *userValues = [user hyp_dictionary];

这就是所有必须做的事情,键将奇迹般地转换为snake_case约定。

{
  "first_name": "John",
  "last_name": "Hyperseed"
}

排除

如果您不希望导出属性/关系,您可以在排除属性或关系的用户信息中添加hyper.nonExportable以禁止导出。

non-exportable

关系

它也支持关系,例如,对于有多个笔记的用户,我们向 Rails 规则 accepts_nested_attributes_for 投诉

"first_name": "John",
"last_name": "Hyperseed",
"notes_attributes": [
  {
    "0": {
      "id": 0,
      "text": "This is the text for the note A"
    },
    "1": {
      "id": 1,
      "text": "This is the text for the note B"
    }
  }
]

如果不想获取嵌套关系,也可以忽略关系

let dictionary = user.hyp_dictionary(using: .none)
"first_name": "John",
"last_name": "Hyperseed"

或者作为数组获取

let dictionary = user.hyp_dictionary(using: .array)
"first_name": "John",
"last_name": "Hyperseed",
"notes": [
  {
    "id": 0,
    "text": "This is the text for the note A"
  },
  {
    "id": 1,
    "text": "This is the text for the note B"
  }
]

安装

SYNCPropertyMapper 通过 CocoaPods 提供。要安装它,只需将以下行添加到您的 Podfile

use_frameworks!

pod 'SYNCPropertyMapper', '~> 5'

SYNCPropertyMapper 也通过 Carthage 提供。要安装它,只需在 Cartfile 中添加以下行

github "SyncDB/SYNCPropertyMapper" ~> 5.0

贡献

请参考 Hyper 的 playbook 获取贡献指南。

致谢

Hyper 制作了这个。我们是一家对良好代码充满热情的数字传播机构,如果您正在使用这个库,我们可能希望 雇佣您

许可证

SYNCPropertyMapper 在 MIT 许可下提供。有关更多信息,请参阅 LICENSE 文件。