mirror of
https://github.com/zhigang1992/RestKit.git
synced 2026-04-01 09:31:17 +08:00
Fix of RKObjectMappingOperation does not respect forceCollectionMapping (Issue 341)
Includes test cases and fixtures
This commit is contained in:
@@ -355,6 +355,22 @@ BOOL RKObjectIsValueEqualToValue(id sourceValue, id destinationValue) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Handle case where incoming content is collection represented by a dictionary
|
||||
if (relationshipMapping.mapping.forceCollectionMapping) {
|
||||
// If we have forced mapping of a dictionary, map each subdictionary
|
||||
if ([value isKindOfClass:[NSDictionary class]]) {
|
||||
RKLogDebug(@"Collection mapping forced for NSDictionary, mapping each key/value independently...");
|
||||
NSArray* objectsToMap = [NSMutableArray arrayWithCapacity:[value count]];
|
||||
for (id key in value) {
|
||||
NSDictionary* dictionaryToMap = [NSDictionary dictionaryWithObject:[value valueForKey:key] forKey:key];
|
||||
[(NSMutableArray*)objectsToMap addObject:dictionaryToMap];
|
||||
}
|
||||
value = objectsToMap;
|
||||
} else {
|
||||
RKLogWarning(@"Collection mapping forced but mappable objects is of type '%@' rather than NSDictionary", NSStringFromClass([value class]));
|
||||
}
|
||||
}
|
||||
|
||||
// Handle case where incoming content is a single object, but we want a collection
|
||||
Class relationshipType = [self.objectMapping classForProperty:relationshipMapping.destinationKeyPath];
|
||||
BOOL mappingToCollection = (relationshipType &&
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
251939E913AABED40073A39B /* DynamicKeys.json in Resources */ = {isa = PBXBuildFile; fileRef = 251939E613AABED40073A39B /* DynamicKeys.json */; };
|
||||
251939EA13AABED40073A39B /* error.json in Resources */ = {isa = PBXBuildFile; fileRef = 251939E713AABED40073A39B /* error.json */; };
|
||||
251939EB13AABED40073A39B /* errors.json in Resources */ = {isa = PBXBuildFile; fileRef = 251939E813AABED40073A39B /* errors.json */; };
|
||||
251939ED13ABA06D0073A39B /* DynamicKeysWithRelationship.json in Resources */ = {isa = PBXBuildFile; fileRef = 251939EC13ABA06D0073A39B /* DynamicKeysWithRelationship.json */; };
|
||||
251939ED13ABA06D0073A39B /* DynamicKeysWithNestedRelationship.json in Resources */ = {isa = PBXBuildFile; fileRef = 251939EC13ABA06D0073A39B /* DynamicKeysWithNestedRelationship.json */; };
|
||||
251D14AC133597B800959061 /* RKManagedObjectLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 251D14AA133597B800959061 /* RKManagedObjectLoader.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
251D14AD133597B800959061 /* RKManagedObjectLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 251D14AB133597B800959061 /* RKManagedObjectLoader.m */; };
|
||||
2523363E11E7A1F00048F9B4 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3F6C3A9510FE7524008F47C5 /* UIKit.framework */; };
|
||||
@@ -303,6 +303,7 @@
|
||||
3F71ED3413748536006281CA /* RKObjectMappingProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 3F71ED3213748536006281CA /* RKObjectMappingProvider.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
3F71ED3513748536006281CA /* RKObjectMappingProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 3F71ED3313748536006281CA /* RKObjectMappingProvider.m */; };
|
||||
3FD12C851379AD64008B996A /* RKRouter.h in Headers */ = {isa = PBXBuildFile; fileRef = 3FD12C841379AD64008B996A /* RKRouter.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
40A0C79C14212B3B00D36DD2 /* DynamicKeysWithRelationship.json in Resources */ = {isa = PBXBuildFile; fileRef = 409341EC14211E7900EF4609 /* DynamicKeysWithRelationship.json */; };
|
||||
57D7EA2713D98672000E4E63 /* NSNumberCreator.m in Sources */ = {isa = PBXBuildFile; fileRef = 57D7EA2213D98672000E4E63 /* NSNumberCreator.m */; };
|
||||
57D7EA2813D98672000E4E63 /* UIConsoleLog.m in Sources */ = {isa = PBXBuildFile; fileRef = 57D7EA2313D98672000E4E63 /* UIConsoleLog.m */; };
|
||||
57D7EA2913D98672000E4E63 /* UIExpectation.m in Sources */ = {isa = PBXBuildFile; fileRef = 57D7EA2413D98672000E4E63 /* UIExpectation.m */; };
|
||||
@@ -465,7 +466,7 @@
|
||||
251939E613AABED40073A39B /* DynamicKeys.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = DynamicKeys.json; sourceTree = "<group>"; };
|
||||
251939E713AABED40073A39B /* error.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = error.json; sourceTree = "<group>"; };
|
||||
251939E813AABED40073A39B /* errors.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = errors.json; sourceTree = "<group>"; };
|
||||
251939EC13ABA06D0073A39B /* DynamicKeysWithRelationship.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = DynamicKeysWithRelationship.json; sourceTree = "<group>"; };
|
||||
251939EC13ABA06D0073A39B /* DynamicKeysWithNestedRelationship.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = DynamicKeysWithNestedRelationship.json; sourceTree = "<group>"; };
|
||||
251D14AA133597B800959061 /* RKManagedObjectLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RKManagedObjectLoader.h; sourceTree = "<group>"; };
|
||||
251D14AB133597B800959061 /* RKManagedObjectLoader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKManagedObjectLoader.m; sourceTree = "<group>"; };
|
||||
2523360511E79F090048F9B4 /* libRestKitThree20.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRestKitThree20.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
@@ -739,6 +740,7 @@
|
||||
3F71ED3213748536006281CA /* RKObjectMappingProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RKObjectMappingProvider.h; sourceTree = "<group>"; };
|
||||
3F71ED3313748536006281CA /* RKObjectMappingProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKObjectMappingProvider.m; sourceTree = "<group>"; };
|
||||
3FD12C841379AD64008B996A /* RKRouter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RKRouter.h; path = Code/ObjectMapping/RKRouter.h; sourceTree = SOURCE_ROOT; };
|
||||
409341EC14211E7900EF4609 /* DynamicKeysWithRelationship.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = DynamicKeysWithRelationship.json; sourceTree = "<group>"; };
|
||||
57D7EA2213D98672000E4E63 /* NSNumberCreator.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = NSNumberCreator.m; path = ../UISpecRunner/NSNumberCreator.m; sourceTree = "<group>"; };
|
||||
57D7EA2313D98672000E4E63 /* UIConsoleLog.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = UIConsoleLog.m; path = ../UISpecRunner/UIConsoleLog.m; sourceTree = "<group>"; };
|
||||
57D7EA2413D98672000E4E63 /* UIExpectation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = UIExpectation.m; path = ../UISpecRunner/UIExpectation.m; sourceTree = "<group>"; };
|
||||
@@ -1402,7 +1404,8 @@
|
||||
children = (
|
||||
252CF8B713E255B90093BBD6 /* Dynamic */,
|
||||
2515E7B913B36A7D00E013A4 /* ArrayOfResults.json */,
|
||||
251939EC13ABA06D0073A39B /* DynamicKeysWithRelationship.json */,
|
||||
409341EC14211E7900EF4609 /* DynamicKeysWithRelationship.json */,
|
||||
251939EC13ABA06D0073A39B /* DynamicKeysWithNestedRelationship.json */,
|
||||
251939E613AABED40073A39B /* DynamicKeys.json */,
|
||||
251939E713AABED40073A39B /* error.json */,
|
||||
251939E813AABED40073A39B /* errors.json */,
|
||||
@@ -2023,6 +2026,7 @@
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
40A0C79C14212B3B00D36DD2 /* DynamicKeysWithRelationship.json in Resources */,
|
||||
25952EE1136F563E00D04F93 /* blake.png in Resources */,
|
||||
25952EE2136F563E00D04F93 /* ComplexNestedUser.json in Resources */,
|
||||
25952EE3136F563E00D04F93 /* Foursquare.json in Resources */,
|
||||
@@ -2036,7 +2040,7 @@
|
||||
251939E913AABED40073A39B /* DynamicKeys.json in Resources */,
|
||||
251939EA13AABED40073A39B /* error.json in Resources */,
|
||||
251939EB13AABED40073A39B /* errors.json in Resources */,
|
||||
251939ED13ABA06D0073A39B /* DynamicKeysWithRelationship.json in Resources */,
|
||||
251939ED13ABA06D0073A39B /* DynamicKeysWithNestedRelationship.json in Resources */,
|
||||
25BA443513ABB34900ADC7D0 /* tab_data.xml in Resources */,
|
||||
2515E7BA13B36A7D00E013A4 /* ArrayOfResults.json in Resources */,
|
||||
252CF8B913E255D70093BBD6 /* boy.json in Resources */,
|
||||
|
||||
33
Specs/Fixtures/JSON/DynamicKeysWithNestedRelationship.json
Normal file
33
Specs/Fixtures/JSON/DynamicKeysWithNestedRelationship.json
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"groups":[
|
||||
{
|
||||
"name":"restkit",
|
||||
"users": {
|
||||
"blake": {
|
||||
"id": 31337,
|
||||
"website": "http://restkit.org/"
|
||||
},
|
||||
"rachit": {
|
||||
"id": 7,
|
||||
"website": "http://www.twotoasters.com/",
|
||||
"address": {
|
||||
"city": "New York",
|
||||
"state": "New York"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name":"others",
|
||||
"users":{
|
||||
"bjorn": {
|
||||
"id": 10,
|
||||
"address": {
|
||||
"city": "Gothenburg",
|
||||
"country": "Sweden"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -136,6 +136,68 @@
|
||||
|
||||
@end
|
||||
|
||||
@interface RKExampleGroupWithUserArray : NSObject {
|
||||
NSString * _name;
|
||||
NSArray* _users;
|
||||
}
|
||||
|
||||
@property (nonatomic, retain) NSString* name;
|
||||
@property (nonatomic, retain) NSArray* users;
|
||||
|
||||
@end
|
||||
|
||||
@implementation RKExampleGroupWithUserArray
|
||||
|
||||
@synthesize name = _name;
|
||||
@synthesize users = _users;
|
||||
|
||||
+ (RKExampleGroupWithUserArray*)group {
|
||||
return [[self new] autorelease];
|
||||
}
|
||||
|
||||
// isEqual: is consulted by the mapping operation
|
||||
// to determine if assocation values should be set
|
||||
- (BOOL)isEqual:(id)object {
|
||||
if ([object isKindOfClass:[RKExampleGroupWithUserArray class]]) {
|
||||
return [[(RKExampleGroupWithUserArray*)object name] isEqualToString:self.name];
|
||||
} else {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface RKExampleGroupWithUserSet : NSObject {
|
||||
NSString * _name;
|
||||
NSSet* _users;
|
||||
}
|
||||
|
||||
@property (nonatomic, retain) NSString* name;
|
||||
@property (nonatomic, retain) NSSet* users;
|
||||
|
||||
@end
|
||||
|
||||
@implementation RKExampleGroupWithUserSet
|
||||
|
||||
@synthesize name = _name;
|
||||
@synthesize users = _users;
|
||||
|
||||
+ (RKExampleGroupWithUserSet*)group {
|
||||
return [[self new] autorelease];
|
||||
}
|
||||
|
||||
// isEqual: is consulted by the mapping operation
|
||||
// to determine if assocation values should be set
|
||||
- (BOOL)isEqual:(id)object {
|
||||
if ([object isKindOfClass:[RKExampleGroupWithUserSet class]]) {
|
||||
return [[(RKExampleGroupWithUserSet*)object name] isEqualToString:self.name];
|
||||
} else {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma mark -
|
||||
@@ -454,6 +516,123 @@
|
||||
[expectThat(user.address.city) should:be(@"New York")];
|
||||
}
|
||||
|
||||
- (void)itShouldMapANestedArrayOfObjectsWithDynamicKeysAndArrayRelationships {
|
||||
RKObjectMapping* mapping = [RKObjectMapping mappingForClass:[RKExampleGroupWithUserArray class]];
|
||||
[mapping mapAttributes:@"name", nil];
|
||||
|
||||
|
||||
RKObjectMapping* userMapping = [RKObjectMapping mappingForClass:[RKExampleUser class]];
|
||||
userMapping.forceCollectionMapping = YES;
|
||||
[userMapping mapKeyOfNestedDictionaryToAttribute:@"name"];
|
||||
[mapping mapKeyPath:@"users" toRelationship:@"users" withMapping:userMapping];
|
||||
|
||||
RKObjectMapping* addressMapping = [RKObjectMapping mappingForClass:[RKSpecAddress class]];
|
||||
[addressMapping mapAttributes:
|
||||
@"city", @"city",
|
||||
@"state", @"state",
|
||||
@"country", @"country",
|
||||
nil
|
||||
];
|
||||
[userMapping mapKeyPath:@"(name).address" toRelationship:@"address" withMapping:addressMapping];
|
||||
RKObjectMappingProvider* provider = [[RKObjectMappingProvider new] autorelease];
|
||||
[provider setMapping:mapping forKeyPath:@"groups"];
|
||||
|
||||
id userInfo = RKSpecParseFixture(@"DynamicKeysWithNestedRelationship.json");
|
||||
RKObjectMapper* mapper = [RKObjectMapper mapperWithObject:userInfo mappingProvider:provider];
|
||||
RKObjectMappingResult* result = [mapper performMapping];
|
||||
|
||||
NSArray* groups = [result asCollection];
|
||||
[expectThat([groups isKindOfClass:[NSArray class]]) should:be(YES)];
|
||||
[expectThat([groups count]) should:be(2)];
|
||||
|
||||
RKExampleGroupWithUserArray* group = [groups objectAtIndex:0];
|
||||
[expectThat([group isKindOfClass:[RKExampleGroupWithUserArray class]]) should:be(YES)];
|
||||
[expectThat(group.name) should:be(@"restkit")];
|
||||
NSArray * users = group.users;
|
||||
[expectThat([users count]) should:be(2)];
|
||||
RKExampleUser* user = [users objectAtIndex:0];
|
||||
[expectThat([user isKindOfClass:[RKExampleUser class]]) should:be(YES)];
|
||||
[expectThat(user.name) should:be(@"blake")];
|
||||
user = [users objectAtIndex:1];
|
||||
[expectThat([user isKindOfClass:[RKExampleUser class]]) should:be(YES)];
|
||||
[expectThat(user.name) should:be(@"rachit")];
|
||||
[expectThat(user.address) shouldNot:be(nil)];
|
||||
[expectThat(user.address.city) should:be(@"New York")];
|
||||
|
||||
group = [groups objectAtIndex:1];
|
||||
[expectThat([group isKindOfClass:[RKExampleGroupWithUserArray class]]) should:be(YES)];
|
||||
[expectThat(group.name) should:be(@"others")];
|
||||
users = group.users;
|
||||
[expectThat([users count]) should:be(1)];
|
||||
user = [users objectAtIndex:0];
|
||||
[expectThat([user isKindOfClass:[RKExampleUser class]]) should:be(YES)];
|
||||
[expectThat(user.name) should:be(@"bjorn")];
|
||||
[expectThat(user.address) shouldNot:be(nil)];
|
||||
[expectThat(user.address.city) should:be(@"Gothenburg")];
|
||||
[expectThat(user.address.country) should:be(@"Sweden")];
|
||||
}
|
||||
|
||||
- (void)itShouldMapANestedArrayOfObjectsWithDynamicKeysAndSetRelationships {
|
||||
RKObjectMapping* mapping = [RKObjectMapping mappingForClass:[RKExampleGroupWithUserSet class]];
|
||||
[mapping mapAttributes:@"name", nil];
|
||||
|
||||
|
||||
RKObjectMapping* userMapping = [RKObjectMapping mappingForClass:[RKExampleUser class]];
|
||||
userMapping.forceCollectionMapping = YES;
|
||||
[userMapping mapKeyOfNestedDictionaryToAttribute:@"name"];
|
||||
[mapping mapKeyPath:@"users" toRelationship:@"users" withMapping:userMapping];
|
||||
|
||||
RKObjectMapping* addressMapping = [RKObjectMapping mappingForClass:[RKSpecAddress class]];
|
||||
[addressMapping mapAttributes:
|
||||
@"city", @"city",
|
||||
@"state", @"state",
|
||||
@"country", @"country",
|
||||
nil
|
||||
];
|
||||
[userMapping mapKeyPath:@"(name).address" toRelationship:@"address" withMapping:addressMapping];
|
||||
RKObjectMappingProvider* provider = [[RKObjectMappingProvider new] autorelease];
|
||||
[provider setMapping:mapping forKeyPath:@"groups"];
|
||||
|
||||
id userInfo = RKSpecParseFixture(@"DynamicKeysWithNestedRelationship.json");
|
||||
RKObjectMapper* mapper = [RKObjectMapper mapperWithObject:userInfo mappingProvider:provider];
|
||||
RKObjectMappingResult* result = [mapper performMapping];
|
||||
|
||||
NSArray* groups = [result asCollection];
|
||||
[expectThat([groups isKindOfClass:[NSArray class]]) should:be(YES)];
|
||||
[expectThat([groups count]) should:be(2)];
|
||||
|
||||
RKExampleGroupWithUserSet* group = [groups objectAtIndex:0];
|
||||
[expectThat([group isKindOfClass:[RKExampleGroupWithUserSet class]]) should:be(YES)];
|
||||
[expectThat(group.name) should:be(@"restkit")];
|
||||
|
||||
|
||||
NSSortDescriptor * sortByName =[[[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES] autorelease];
|
||||
NSArray * descriptors = [NSArray arrayWithObject:sortByName];;
|
||||
NSArray * users = [group.users sortedArrayUsingDescriptors:descriptors];
|
||||
[expectThat([users count]) should:be(2)];
|
||||
RKExampleUser* user = [users objectAtIndex:0];
|
||||
[expectThat([user isKindOfClass:[RKExampleUser class]]) should:be(YES)];
|
||||
[expectThat(user.name) should:be(@"blake")];
|
||||
user = [users objectAtIndex:1];
|
||||
[expectThat([user isKindOfClass:[RKExampleUser class]]) should:be(YES)];
|
||||
[expectThat(user.name) should:be(@"rachit")];
|
||||
[expectThat(user.address) shouldNot:be(nil)];
|
||||
[expectThat(user.address.city) should:be(@"New York")];
|
||||
|
||||
group = [groups objectAtIndex:1];
|
||||
[expectThat([group isKindOfClass:[RKExampleGroupWithUserSet class]]) should:be(YES)];
|
||||
[expectThat(group.name) should:be(@"others")];
|
||||
users = [group.users sortedArrayUsingDescriptors:descriptors];
|
||||
[expectThat([users count]) should:be(1)];
|
||||
user = [users objectAtIndex:0];
|
||||
[expectThat([user isKindOfClass:[RKExampleUser class]]) should:be(YES)];
|
||||
[expectThat(user.name) should:be(@"bjorn")];
|
||||
[expectThat(user.address) shouldNot:be(nil)];
|
||||
[expectThat(user.address.city) should:be(@"Gothenburg")];
|
||||
[expectThat(user.address.country) should:be(@"Sweden")];
|
||||
}
|
||||
|
||||
|
||||
- (void)itShouldBeAbleToMapFromAUserObjectToADictionary {
|
||||
RKObjectMapping* mapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
|
||||
RKObjectAttributeMapping* idMapping = [RKObjectAttributeMapping mappingFromKeyPath:@"userID" toKeyPath:@"id"];
|
||||
|
||||
Reference in New Issue
Block a user