要安装 Milk,只需将以下行添加到您的 Podfile 中
pod "MLObject"
🥛
什么是 Milk?在这里,我们使用 Realm。虽然它有一些局限性(线程,通知),但在很多方面都相当出色。您可以轻松地将模型持久化到磁盘,拥有全面的观察者系统,强大的查询功能,以及更多。
我们还使用 JSON 进行客户端服务器通信,我们非常希望自动解析为实际的实例对象,因为为每个模型分别编写解析器是:a. ) 非常耗时,b. ) 很多不必要的样板代码,c. ) 容易出错。
Realm 有 一些内置支持,但它对我们想要做的还不够。
没问题,对吧?有很多框架,如 JSONModel,可以自动将 JSON 解析为模型对象。嗯,是的,但如果应用程序中的很大一部分仍然使用 Objective-C(因为遗留原因),并且 Realm 和这些 JSON 解析框架都需要您对象继承自它们的基类,那就不行了。
该怎么办?嗯,我们决定问题的答案是要编写我们自己的框架,该框架可以直接将 JSON 解析为 Realm 对象。我们称之为 Milk :)。
让我们看看它能够做什么
一个基本示例
在最简单的情况下,只需从 MLObject
继承并添加您需要的属性
@import MLObject;
@interface Cat : MLObject
@property NSString *catID;
@property NSString *preferredName;
@end
现在您可以通过执行 [Cat importedFromJSON:]
(或如果您只想解析对象而不将其导入 Realm,则使用 [Cat convertedFromJSON:]
)来从 JSON 解析 Cat
对象。
Milk可以自动将snake_case的JSON键名映射到lowerCamelCase的对象名。如果属性名包含缩写(例如上面示例中的catID
),这也适用。所以,对于上面的示例,下面两个方法都适用。
{
cat_id: "19378372",
preferred_name: "Jellybean"
}
和
{
catID: "19378372",
preferredName: "Jellybean"
}
。
关于处理大量对象的性能,请参阅[这里](#performance-with-many-objects)。
通常情况下,我们希望一次性解析多个对象。在Milk中,您可以通过执行[Cat importArrayOfObjectsFromJSON:]
来高效地执行此操作(即在单个Realm写事务中)。
如果JSON结构不符合您的模型结构怎么办?请参阅[这里](#what-if-the-json-structure-doesnt-match-your-model-structure)。
服务器并不总是以您想要的JSON结构(即与您的模型相匹配)向您提供JSON。考虑以下示例
{
cat_id: "19378372",
name: "Jellybean",
meta: {
coordinates: {
lon: 4.886
}
},
last_known_latitude: 52.374
}
以下是以下模型结构
@import MLObject;
@interface Location : MLObject
@property NSNumber<RLMDouble> *latitude;
@property NSNumber<RLMDouble> *longitude;
@end
@interface Cat : MLObject
@property NSString *catID;
@property NSString *name;
@property Location *location;
@end
如您所见,JSON结构与管理结构相差甚远,所以在这种情况下,我们的Cat
通常无法解析。但是,使用Milk解决这个问题非常简单。只需实现fromJSONMapping
如下所示:
@implementation Cat
+ (NSDictionary<NSString *, NSString *> *)fromJSONMapping {
return @{
@"location" : @"meta.coordinates",
@"location.latitude" : @"last_known_latitude"
};
}
@end
花点时间看看这里发生了什么。我们在JSON中向下查找(使用键路径)以从Location
对象,然后使用last_known_latitude
将其完整化。
能够将任何JSON结构映射到任何模型结构,意味着客户端设置模型的方式可以完全独立于后端设置的模型方式。很酷,对吧?
关于1的说明
Location
对象也需要实现fromJSONMapping
,以解决lon
JSON键与longitude
属性名不匹配的问题。
@implementation Location
+ (NSDictionary<NSString *, NSString *> *)fromJSONMapping {
return @{
@"latitude" : @"lat",
@"longitude" : @"lon"
};
}
@end
关于2的说明
如果Location
对象,那么在这里指定的latitude
属性值将被last_known_latitude
下找到的值覆盖。
将对象转换为JSON
要将对象转换回JSON,只需调用对象的toJSON
方法。这将返回一个包含对象属性名称的字典
,以snake_case命名映射到其相应的值(即,对每个值都调用了toJSON
)。
您可以使用toJSONMapping
覆盖默认的JSON键。这再次支持键路径。例如,您可以将一个Cat
对象转换为以下JSON
{
cat_id: "19378372",
name_data: {
preferred: "Jellybean"
}
}
通过实现如下Cat
的toJSONMapping
@implementation Cat
+ (NSDictionary<NSString *, NSString *> *)toJSONMapping {
return @{
@"preferredName" : @"name_data.preferred"
};
}
@end
注意事项
您可能想知道是否有某些内容解析失败以及原因。在简单情况下这可能是显而易见的,但在导入大量对象时,很容易错过其中一些对象在解析中丢失。为了帮助解决这个问题,Milk会在解析失败时打印一条警告,指示它试图解析的JSON以及它试图解析的类型。