Mantleソース学習(二)
7491 ワード
MTLJSONSerializing
このプロトコルは、データ変換間のルールを定義します.MTLModelサブクラスを実装する必要があります.
MTLJSONAdapter
このクラスはデータ変換のコアクラスに属し、変換中にこの関数を手動で呼び出す必要があります.
この関数の流れ:まずMTLJSOnAdapterオブジェクト を初期化する
この初期化手法では,主にJSOnkeyPathsByPropertyKeyで定義された正当性をチェックし,keyの対応関係をキャッシュする.次のコードを使用します.
キーごとに対応するNSValueTransformer(データ解析変換メソッド)をキャッシュし、辞書にキャッシュします.これらの方法の中にはModelによるものがある.以下のいくつかはModelで実装された変換方式のいくつかの例であり、この関数のフォーマットはkeyのname+JSOnTransformerである.
他の一般的なデータ型の変換は、デフォルトのNSValueTransformerを直接使用して行うことができます.Modelで対応する方法を実装する必要はありません.、次いで、システムはデータのシーケンス化を開始する.このステップでは、 というコードを呼び出します.
この関数では、まずModelがclassForParsingJSONDictionaryという関数を実現したかどうかを判断し、実現したらJSONをこの関数で返されるデータ型に変換する必要があります.
上記のプロトコルが実装されていない場合.データ解析が始まり、プロセス全体が次のようになります.
以上、JSON---->Modelの手順について詳しく説明しました.他の複雑な機能はしばらく注目されていません
このプロトコルは、データ変換間のルールを定義します.MTLModelサブクラスを実装する必要があります.
// key JSON key path 。 : key , JSON 。
+ (NSDictionary *)JSONKeyPathsByPropertyKey;
// , Model key NSValueTransformer, +(NSValueTransformer *)key+JSONTransformerForKey; 。
+ (NSValueTransformer *)JSONTransformerForKey:(NSString *)key;
// 。
+ (Class)classForParsingJSONDictionary:(NSDictionary *)JSONDictionary;
MTLJSONAdapter
このクラスはデータ変換のコアクラスに属し、変換中にこの関数を手動で呼び出す必要があります.
// JSON 。
+ (id)modelOfClass:(Class)modelClass fromJSONDictionary:(NSDictionary *)JSONDictionary error:(NSError **)error
この関数の流れ:
MTLJSONAdapter *adapter = [[self alloc] initWithModelClass:modelClass];
この初期化手法では,主にJSOnkeyPathsByPropertyKeyで定義された正当性をチェックし,keyの対応関係をキャッシュする.次のコードを使用します.
_valueTransformersByPropertyKey = [self.class valueTransformersForModelClass:modelClass];
キーごとに対応するNSValueTransformer(データ解析変換メソッド)をキャッシュし、辞書にキャッシュします.これらの方法の中にはModelによるものがある.以下のいくつかはModelで実装された変換方式のいくつかの例であり、この関数のフォーマットはkeyのname+JSOnTransformerである.
// NSURL
+ (NSValueTransformer *)HTMLURLJSONTransformer {
return [NSValueTransformer valueTransformerForName:MTLURLValueTransformerName];
}
// key-value 。 Map
+ (NSValueTransformer *)stateJSONTransformer {
return [NSValueTransformer mtl_valueMappingTransformerWithDictionary:@{
@"open": @(GHIssueStateOpen),
@"closed": @(GHIssueStateClosed)
}];
}
// (Model Model),MTLRecursiveUserModel )
+ (NSValueTransformer *)ownerJSONTransformer {
return [MTLJSONAdapter dictionaryTransformerWithModelClass:MTLRecursiveUserModel.class];
}
// (Model ),MTLRecursiveUserModel )
+ (NSValueTransformer *)usersJSONTransformer {
return [MTLJSONAdapter arrayTransformerWithModelClass:MTLRecursiveUserModel.class];
}
他の一般的なデータ型の変換は、デフォルトのNSValueTransformerを直接使用して行うことができます.Modelで対応する方法を実装する必要はありません.
[adapter modelFromJSONDictionary:JSONDictionary error:error];
この関数では、まずModelがclassForParsingJSONDictionaryという関数を実現したかどうかを判断し、実現したらJSONをこの関数で返されるデータ型に変換する必要があります.
if ([self.modelClass respondsToSelector:@selector(classForParsingJSONDictionary:)]) {
Class class = [self.modelClass classForParsingJSONDictionary:JSONDictionary];
//
if (class == nil) {
if (error != NULL) {
NSDictionary *userInfo = @{
NSLocalizedDescriptionKey: NSLocalizedString(@"Could not parse JSON", @""),
NSLocalizedFailureReasonErrorKey: NSLocalizedString(@"No model class could be found to parse the JSON dictionary.", @"")
};
*error = [NSError errorWithDomain:MTLJSONAdapterErrorDomain code:MTLJSONAdapterErrorNoClassFound userInfo:userInfo];
}
return nil;
}
// , MTLJSONSerializing 、 MTLJSONAdapter , 。 return, 。
if (class != self.modelClass) {
NSAssert([class conformsToProtocol:@protocol(MTLJSONSerializing)], @"Class %@ returned from +classForParsingJSONDictionary: does not conform to ", class);
MTLJSONAdapter *otherAdapter = [self JSONAdapterForModelClass:class error:error];
return [otherAdapter modelFromJSONDictionary:JSONDictionary error:error];
}
}
上記のプロトコルが実装されていない場合.データ解析が始まり、プロセス全体が次のようになります.
NSMutableDictionary *dictionaryValue = [[NSMutableDictionary alloc] initWithCapacity:JSONDictionary.count];
// key, key
for (NSString *propertyKey in [self.modelClass propertyKeys]) {
id JSONKeyPaths = self.JSONKeyPathsByPropertyKey[propertyKey];
if (JSONKeyPaths == nil) continue;
id value;
// key value
if ([JSONKeyPaths isKindOfClass:NSArray.class]) {
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
for (NSString *keyPath in JSONKeyPaths) {
BOOL success = NO;
id value = [JSONDictionary mtl_valueForJSONKeyPath:keyPath success:&success error:error];
if (!success) return nil;
if (value != nil) dictionary[keyPath] = value;
}
value = dictionary;
} else {
BOOL success = NO;
value = [JSONDictionary mtl_valueForJSONKeyPath:JSONKeyPaths success:&success error:error];
if (!success) return nil;
}
if (value == nil) continue;
@try {
// key NSValueTransformer, NSValueTransformer
NSValueTransformer *transformer = self.valueTransformersByPropertyKey[propertyKey];
if (transformer != nil) {
// Map NSNull -> nil for the transformer, and then back for the
// dictionary we're going to insert into.
if ([value isEqual:NSNull.null]) value = nil;
if ([transformer respondsToSelector:@selector(transformedValue:success:error:)]) {
id errorHandlingTransformer = (id)transformer;
BOOL success = YES;
// new MTLJSONAdapter, , value 。
value = [errorHandlingTransformer transformedValue:value success:&success error:error];
if (!success) return nil;
} else {
//
value = [transformer transformedValue:value];
}
if (value == nil) value = NSNull.null;
}
dictionaryValue[propertyKey] = value;
} @catch (NSException *ex) {
NSLog(@"*** Caught exception %@ parsing JSON key path \"%@\" from: %@", ex, JSONKeyPaths, JSONDictionary);
// Fail fast in Debug builds.
#if DEBUG
@throw ex;
#else
if (error != NULL) {
NSDictionary *userInfo = @{
NSLocalizedDescriptionKey: ex.description,
NSLocalizedFailureReasonErrorKey: ex.reason,
MTLJSONAdapterThrownExceptionErrorKey: ex
};
*error = [NSError errorWithDomain:MTLJSONAdapterErrorDomain code:MTLJSONAdapterErrorExceptionThrown userInfo:userInfo];
}
return nil;
#endif
}
}
// KVC value key, modelWithDictionary MTLModel , (instancetype)initWithDictionary:(NSDictionary *)dictionaryValue error:(NSError **)error; KVC , 。
id model = [self.modelClass modelWithDictionary:dictionaryValue error:error];
以上、JSON---->Modelの手順について詳しく説明しました.他の複雑な機能はしばらく注目されていません