如何使用 restkit 忽略已发布对象上的空属性

Posted

技术标签:

【中文标题】如何使用 restkit 忽略已发布对象上的空属性【英文标题】:How do I ignore empty properties on posted objects using restkit 【发布时间】:2015-08-06 03:20:46 【问题描述】:

我正在恢复一个最初使用 RestKit 0.10 的旧项目,现在正在使用 RestKit 0.24。旧版本仍然可以使用,但不幸的是,RestKit 0.10 不兼容 64 位,因此不会提交到 AppStore(无论如何肯定是时候更新了)。

我无法正确发布对象。在 RestKit 0.10 中,没有值的属性不会发送到服务器,而在 RestKit 0.20 中似乎它们是。我尝试将assignsDefaultValueForMissingAttributes 明确设置为NO,但似乎没有什么不同。

服务器需要以下格式:

"response": "assessment_id":"1","time_taken":"60",
 "answer": [
      "question_number": 1, "answer_value": 3,
      "question_number": 2, "answer_value": 2,
      "question_number": 3, "answer_value": 1,
 ]

我设置了一个对象CompletedAssessment,其中包含一个Response 对象和一个Answer 对象数组。 (请注意,当从服务器接收到这些对象时,需要接收的属性比需要发送的属性多得多)。

@interface CompletedAssessment : NSObject 
    Response *response;
    NSArray *answers;


@interface Answer : NSObject 
    NSNumber *identifier;
    NSNumber *responseId;
    NSNumber *questionNumber;
    NSString *answerHistory;
    NSString *answerValue;
    NSString *answerText;
    NSNumber *timeTaken;


@interface Response : NSObject 
    NSNumber *identifier;
    NSNumber *assessmentId;
    NSNumber *timeTaken;
    NSNumber *clientId;
    NSString *assessmentShortName;
    NSString *score;
    NSString *interpretation;
    NSString *dateCreated;
    NSString *localTime;

我将映射设置如下:

RKObjectMapping *answerMapping = [RKObjectMapping mappingForClass:[Answer class]];
answerMapping.assignsDefaultValueForMissingAttributes = NO;

[answerMapping addAttributeMappingsFromDictionary:@
                                                  @"id": @"identifier",
                                                  @"response_id": @"responseId",
                                                  @"question_number": @"questionNumber",
                                                  @"answer_history": @"answerHistory",
                                                  @"answer_value": @"answerValue",
                                                  @"answer_text": @"answerText",
                                                  @"time_taken": @"timeTaken"
                                                  ];

RKObjectMapping *responseMapping = [RKObjectMapping mappingForClass:[Response class]];
responseMapping.assignsDefaultValueForMissingAttributes = NO;

[responseMapping addAttributeMappingsFromDictionary:@
                                                   @"id": @"identifier",
                                                   @"client_id": @"clientId",
                                                   @"assessment_id": @"assessmentId",
                                                   @"time_taken": @"timeTaken",
                                                   @"score": @"score",
                                                   @"assessment_short_name": @"assessmentShortName",
                                                   @"interpretation": @"interpretation",
                                                   @"created": @"dateCreated",
                                                   @"local_time": @"localTime"
                                                   ];

RKObjectMapping *completedAssessmentMapping = [RKObjectMapping mappingForClass:[CompletedAssessment class]];
completedAssessmentMapping.assignsDefaultValueForMissingAttributes = NO;

[completedAssessmentMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"response" toKeyPath:@"response" withMapping:responseMapping]];
[completedAssessmentMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"answer" toKeyPath:@"answers" withMapping:answerMapping]];

RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:completedAssessmentMapping method:RKRequestMethodGET pathPattern:nil keyPath:@"data.completedAssessment" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[[RKObjectManager sharedManager] addResponseDescriptor:responseDescriptor];
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:[completedAssessmentMapping inverseMapping] objectClass:[CompletedAssessment class] rootKeyPath:nil method:RKRequestMethodPOST];
[[RKObjectManager sharedManager] addRequestDescriptor:requestDescriptor];

[objectManager.router.routeSet addRoute:[RKRoute
                                         routeWithClass:[CompletedAssessment class]
                                         pathPattern:@"clients/:response.clientId/responses"
                                         method:RKRequestMethodPOST]] ;

日志显示最终 JSON 以这种格式出现:

"response":
    "interpretation":null,"id":null,"score":null,"client_id":15,"local_time":"2015-8-6 13:8:34","time_taken":5,"assessment_short_name":null,"assessment_id":8,"created":null,
"answer":[
    "answer_value":"0","id":null,"answer_text":null,"answer_history":null,"time_taken":null,"response_id":null,"question_number":1,
    "answer_value":"1","id":null,"answer_text":null,"answer_history":null,"time_taken":null,"response_id":null,"question_number":2
]

RestKit 日志记录确认空映射:

restkit.object_mapping:RKMappingOperation.m:873 Mapped relationship object from keyPath 'response' to 'response'. Value: 
"assessment_id" = 8;
"assessment_short_name" = "<null>";
"client_id" = 15;
created = "<null>";
id = "<null>";
interpretation = "<null>";
"local_time" = "2015-8-6 13:8:34";
score = "<null>";
"time_taken" = 5;


restkit.object_mapping:RKMappingOperation.m:715 Mapped attribute value from keyPath 'identifier' to 'id'. Value: (null)
...

请帮忙!

【问题讨论】:

【参考方案1】:

您正在此行中创建一个调用[selfCompletedAssessmentMapping inverseMapping] 的新映射:

RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:[selfCompletedAssessmentMapping inverseMapping] objectClass:[CompletedAssessment class] rootKeyPath:nil method:RKRequestMethodPOST];

将其保存到变量中,并在创建描述符之前将assignsDefaultValueForMissingAttributes 分配给NO

RKObjectMapping *requestMapping = [selfCompletedAssessmentMapping inverseMapping];
requestMapping.assignsDefaultValueForMissingAttributes = NO;
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:requestMapping objectClass:[CompletedAssessment class] rootKeyPath:nil method:RKRequestMethodPOST];

【讨论】:

可悲的是它产生了同样的效果。 RestKit 记录所有文档空属性,服务器响应相同。

以上是关于如何使用 restkit 忽略已发布对象上的空属性的主要内容,如果未能解决你的问题,请参考以下文章

RestKit 对象映射在 BOOL 的空 JSON 值上崩溃

如何忽略像“car”这样的空 json 对象:,这会在使用 jackson 反序列化后导致空 pojos

如何忽略 DataWeave Mule esb 中的空对象

RESTKit:覆盖objectID相同但其他属性发生变化的对象。

RestKit 超时被忽略

RestKit 相同对象上的一对一映射,除了