mirror of
https://github.com/zhigang1992/RestKit.git
synced 2026-04-24 04:46:01 +08:00
Add support for dynamic nesting key serialization. closes #684
This commit is contained in:
@@ -418,7 +418,7 @@ static BOOL RKObjectContainsValueForKeyPaths(id representation, NSArray *keyPath
|
||||
for (RKAttributeMapping *attributeMapping in attributeMappings) {
|
||||
if ([self isCancelled]) return NO;
|
||||
|
||||
if ([attributeMapping.sourceKeyPath isEqualToString:RKObjectMappingNestingAttributeKeyName]) {
|
||||
if ([attributeMapping.sourceKeyPath isEqualToString:RKObjectMappingNestingAttributeKeyName] || [attributeMapping.destinationKeyPath isEqualToString:RKObjectMappingNestingAttributeKeyName]) {
|
||||
RKLogTrace(@"Skipping attribute mapping for special keyPath '%@'", attributeMapping.sourceKeyPath);
|
||||
continue;
|
||||
}
|
||||
@@ -714,18 +714,31 @@ static BOOL RKObjectContainsValueForKeyPaths(id representation, NSArray *keyPath
|
||||
|
||||
- (void)applyNestedMappings
|
||||
{
|
||||
RKAttributeMapping *attributeMapping = [self.objectMapping attributeMappingForKeyOfRepresentation];
|
||||
RKAttributeMapping *attributeMapping = [self.objectMapping mappingForSourceKeyPath:RKObjectMappingNestingAttributeKeyName];
|
||||
if (attributeMapping) {
|
||||
RKLogDebug(@"Found nested mapping definition to attribute '%@'", attributeMapping.destinationKeyPath);
|
||||
id attributeValue = [[self.sourceObject allKeys] lastObject];
|
||||
if (attributeValue) {
|
||||
RKLogDebug(@"Found nesting value of '%@' for attribute '%@'", attributeValue, attributeMapping.destinationKeyPath);
|
||||
_nestedAttributeSubstitution = [[NSDictionary alloc] initWithObjectsAndKeys:attributeValue, attributeMapping.destinationKeyPath, nil];
|
||||
_nestedAttributeSubstitution = @{ attributeMapping.destinationKeyPath: attributeValue };
|
||||
[self applyAttributeMapping:attributeMapping withValue:attributeValue];
|
||||
} else {
|
||||
RKLogWarning(@"Unable to find nesting value for attribute '%@'", attributeMapping.destinationKeyPath);
|
||||
}
|
||||
}
|
||||
|
||||
// Serialization
|
||||
attributeMapping = [self.objectMapping mappingForDestinationKeyPath:RKObjectMappingNestingAttributeKeyName];
|
||||
if (attributeMapping) {
|
||||
RKLogDebug(@"Found nested mapping definition to attribute '%@'", attributeMapping.destinationKeyPath);
|
||||
id attributeValue = [self.sourceObject valueForKeyPath:attributeMapping.sourceKeyPath];
|
||||
if (attributeValue) {
|
||||
RKLogDebug(@"Found nesting value of '%@' for attribute '%@'", attributeValue, attributeMapping.sourceKeyPath);
|
||||
_nestedAttributeSubstitution = @{ attributeMapping.sourceKeyPath: attributeValue };
|
||||
} else {
|
||||
RKLogWarning(@"Unable to find nesting value for attribute '%@'", attributeMapping.destinationKeyPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)cancel
|
||||
|
||||
@@ -96,9 +96,9 @@
|
||||
*/
|
||||
+ (instancetype)requestMapping;
|
||||
|
||||
///---------------------------------
|
||||
/// @name Managing Property Mappings
|
||||
///---------------------------------
|
||||
///----------------------------------
|
||||
/// @name Accessing Property Mappings
|
||||
///----------------------------------
|
||||
|
||||
/**
|
||||
The aggregate collection of attribute and relationship mappings within this object mapping.
|
||||
@@ -109,6 +109,7 @@
|
||||
Returns the property mappings of the receiver in a dictionary, where the keys are the source key paths and the values are instances of `RKAttributeMapping` or `RKRelationshipMapping`.
|
||||
|
||||
@return The property mappings of the receiver in a dictionary, where the keys are the source key paths and the values are instances of `RKAttributeMapping` or `RKRelationshipMapping`.
|
||||
@warning Note this method does not return any property mappings with a `nil` value for the source key path in the dictionary returned.
|
||||
*/
|
||||
@property (nonatomic, readonly) NSDictionary *propertyMappingsBySourceKeyPath;
|
||||
|
||||
@@ -116,6 +117,7 @@
|
||||
Returns the property mappings of the receiver in a dictionary, where the keys are the destination key paths and the values are instances of `RKAttributeMapping` or `RKRelationshipMapping`.
|
||||
|
||||
@return The property mappings of the receiver in a dictionary, where the keys are the destination key paths and the values are instances of `RKAttributeMapping` or `RKRelationshipMapping`.
|
||||
@warning Note this method does not return any property mappings with a `nil` value for the source key path in the dictionary returned.
|
||||
*/
|
||||
@property (nonatomic, readonly) NSDictionary *propertyMappingsByDestinationKeyPath;
|
||||
|
||||
@@ -129,6 +131,24 @@
|
||||
*/
|
||||
@property (nonatomic, readonly) NSArray *relationshipMappings;
|
||||
|
||||
/**
|
||||
Returns the property mapping registered with the receiver with the given source key path.
|
||||
|
||||
@param sourceKeyPath The key path to retrieve.
|
||||
*/
|
||||
- (id)mappingForSourceKeyPath:(NSString *)sourceKeyPath;
|
||||
|
||||
/**
|
||||
Returns the property mapping registered with the receiver with the given destinationKeyPath key path.
|
||||
|
||||
@param destinationKeyPath The key path to retrieve.
|
||||
*/
|
||||
- (id)mappingForDestinationKeyPath:(NSString *)destinationKeyPath;
|
||||
|
||||
///---------------------------
|
||||
/// Managing Property Mappings
|
||||
///---------------------------
|
||||
|
||||
/**
|
||||
Adds a property mapping to the receiver.
|
||||
|
||||
@@ -226,14 +246,26 @@
|
||||
- (void)addAttributeMappingFromKeyOfRepresentationToAttribute:(NSString *)attributeName;
|
||||
|
||||
/**
|
||||
Returns the attribute mapping targeting the key of a nested dictionary in the source JSON.
|
||||
Adds an attribute mapping to a dynamic nesting key from an attribute. The mapped attribute name can then be referenced wthin other attribute mappings to map content under the nesting key path.
|
||||
|
||||
For example, consider that we wish to map a local user object with the properties 'id', 'firstName' and 'email':
|
||||
|
||||
RKUser *user = [RKUser new];
|
||||
user.firstName = @"blake";
|
||||
user.userID = @(1234);
|
||||
user.email = @"blake@restkit.org";
|
||||
|
||||
This attribute mapping corresponds to the attributeName configured via `mapKeyOfNestedDictionaryToAttribute:`
|
||||
|
||||
@return An attribute mapping for the key of a nested dictionary being mapped or nil
|
||||
@see `addAttributeMappingFromKeyOfRepresentationToAttribute:`
|
||||
And we wish to map it into JSON that looks like:
|
||||
|
||||
{ "blake": { "id": 1234, "email": "blake@restkit.org" } }
|
||||
|
||||
We can configure our request mapping to handle this like so:
|
||||
|
||||
RKObjectMapping *mapping = [RKObjectMapping requestMapping];
|
||||
[mapping addAttributeMappingToKeyOfRepresentationFromAttribute:@"firstName"];
|
||||
[mapping addAttributeMappingsFromDictionary:@{ @"(firstName).userID": @"id", @"(firstName).email": @"email" }];
|
||||
*/
|
||||
- (RKAttributeMapping *)attributeMappingForKeyOfRepresentation;
|
||||
- (void)addAttributeMappingToKeyOfRepresentationFromAttribute:(NSString *)attributeName;
|
||||
|
||||
///----------------------------------
|
||||
/// @name Configuring Mapping Options
|
||||
|
||||
@@ -175,6 +175,7 @@ static RKSourceToDesinationKeyTransformationBlock defaultSourceToDestinationKeyT
|
||||
{
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithCapacity:[self.propertyMappings count]];
|
||||
for (RKPropertyMapping *propertyMapping in self.propertyMappings) {
|
||||
if (! propertyMapping.sourceKeyPath) continue;
|
||||
[dictionary setObject:propertyMapping forKey:propertyMapping.sourceKeyPath];
|
||||
}
|
||||
|
||||
@@ -185,6 +186,7 @@ static RKSourceToDesinationKeyTransformationBlock defaultSourceToDestinationKeyT
|
||||
{
|
||||
NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithCapacity:[self.propertyMappings count]];
|
||||
for (RKPropertyMapping *propertyMapping in self.propertyMappings) {
|
||||
if (! propertyMapping.destinationKeyPath) continue;
|
||||
[dictionary setObject:propertyMapping forKey:propertyMapping.destinationKeyPath];
|
||||
}
|
||||
|
||||
@@ -244,11 +246,6 @@ static RKSourceToDesinationKeyTransformationBlock defaultSourceToDestinationKeyT
|
||||
NSStringFromClass([self class]), self, NSStringFromClass(self.objectClass), self.propertyMappings];
|
||||
}
|
||||
|
||||
- (id)mappingForKeyPath:(NSString *)keyPath
|
||||
{
|
||||
return [self mappingForSourceKeyPath:keyPath];
|
||||
}
|
||||
|
||||
- (id)mappingForSourceKeyPath:(NSString *)sourceKeyPath
|
||||
{
|
||||
for (RKPropertyMapping *mapping in self.propertyMappings) {
|
||||
@@ -339,9 +336,9 @@ static RKSourceToDesinationKeyTransformationBlock defaultSourceToDestinationKeyT
|
||||
[self addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:RKObjectMappingNestingAttributeKeyName toKeyPath:attributeName]];
|
||||
}
|
||||
|
||||
- (RKAttributeMapping *)attributeMappingForKeyOfRepresentation
|
||||
- (void)addAttributeMappingToKeyOfRepresentationFromAttribute:(NSString *)attributeName
|
||||
{
|
||||
return [self mappingForKeyPath:RKObjectMappingNestingAttributeKeyName];
|
||||
[self addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:attributeName toKeyPath:RKObjectMappingNestingAttributeKeyName]];
|
||||
}
|
||||
|
||||
- (RKAttributeMapping *)mappingForAttribute:(NSString *)attributeKey
|
||||
|
||||
@@ -448,6 +448,21 @@
|
||||
expect(string).to.equal(@"{\"name\":\"Blake Watters\",\"happy\":false}");
|
||||
}
|
||||
|
||||
- (void)testSerializingWithDynamicNestingAttribute
|
||||
{
|
||||
NSDictionary *object = @{ @"name" : @"blake", @"occupation" : @"Hacker" };
|
||||
RKObjectMapping *mapping = [RKObjectMapping requestMapping];
|
||||
[mapping addAttributeMappingToKeyOfRepresentationFromAttribute:@"name"];
|
||||
[mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"name" toKeyPath:@"(name).name"]];
|
||||
[mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"occupation" toKeyPath:@"(name).job"]];
|
||||
|
||||
NSError *error = nil;
|
||||
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:mapping objectClass:[NSDictionary class] rootKeyPath:nil];
|
||||
NSDictionary *parameters = [RKObjectParameterization parametersWithObject:object requestDescriptor:requestDescriptor error:&error];
|
||||
NSDictionary *expected = @{@"blake": @{@"name": @"blake", @"job": @"Hacker"}};
|
||||
expect(parameters).to.equal(expected);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - Dynamic Request Paramterization
|
||||
|
||||
Reference in New Issue
Block a user