Mapping json with RestKit 0.20.3

2019-07-23 16:16发布

I'm trying to map objects through RestKit 0.20.3, but I'm having those logs for days know:

2013-08-12 18:32:08.158 MyAppIphone[848:5703] E restkit.network:RKResponseMapperOperation.m:304 Failed to parse response data: Loaded an unprocessable response (200) with content type 'application/json'

2013-08-12 18:32:08.174 MyAppIphone[848:5703] E restkit.network:RKObjectRequestOperation.m:238 POST 'myUrl' (200 OK / 0 objects) 

[request=0.1305s mapping=0.0000s total=5.6390s]:
error=Error Domain=org.restkit.RestKit.ErrorDomain Code=-1017 "Loaded an unprocessable response (200) with content type 'application/json'" 

UserInfo=0x1ed5a500 {NSErrorFailingURLKey=myUrl, NSUnderlyingError=0x1ed5b240 "The operation couldn’t be completed. (Cocoa error 3840.)", NSLocalizedDescription=Loaded an unprocessable response (200) with content type 'application/json'}

response.body={"my json content"}

Here is MyData class:

#import <Foundation/Foundation.h>

@interface MyData : NSObject

@property (nonatomic, retain) NSString *criterias;

@end

Here is how I set up my mapper:

- (RKResponseDescriptor*) getDataMapping
{
    // Mapping
    RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[MyData class]];
    [mapping addAttributeMappingsFromDictionary:@{
     @"criteriasHeader":        @"criteriasHeader"
     }];

    // Status code
    NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful);

    // Descriptior
    return [RKResponseDescriptor responseDescriptorWithMapping:mapping method:RKRequestMethodPOST pathPattern:nil keyPath:@"regions" statusCodes:statusCodes];
}

Here my requesting function:

- (void) runRequestWithType:(RequestType)type baseUrl:(NSString *)baseUrlString path:(NSString *)path parameters:(NSDictionary *)parameters mapping:(RKResponseDescriptor *) descriptor
{
    // Print heeader and body from the request and the response
    RKLogConfigureByName("RestKit/Network", RKLogLevelTrace);
    RKLogConfigureByName("Restkit/Network", RKLogLevelDebug);
    RKLogConfigureByName("RestKit/ObjectMapping", RKLogLevelTrace);
    RKLogConfigureByName("Restkit/ObjectMapping", RKLogLevelDebug);

    // Set up the base url
    NSURL *baseUrl = [NSURL URLWithString:baseUrlString];

    //Run request in block
    RKObjectManager *manager = [RKObjectManager managerWithBaseURL:baseUrl];
    [manager addResponseDescriptorsFromArray:@[descriptor]];

    [manager.router.routeSet addRoute:[RKRoute routeWithClass:[MyData class] pathPattern:path method:RKRequestMethodPOST]];
    //[manager getObjectsAtPath:path parameters:parameters success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
    [manager postObject:nil path:path parameters:parameters success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
        if ([self.delegate respondsToSelector:@selector(requestDidSucceedWithType:andResponse:)]) {
            [self.delegate requestDidSucceedWithType:type andResponse:[mappingResult firstObject]];
        }
    } failure:^(RKObjectRequestOperation *operation, NSError *error) {
        if ([self.delegate respondsToSelector:@selector(requestDidFailWithError:andError:)]) {
            [self.delegate requestDidFailWithType:type andError:error];
        }
    }];
}

PS: I tried with a shorter JSON, it works well.

Did I do something wrong?

Could you help me, thanks.

2条回答
三岁会撩人
2楼-- · 2019-07-23 16:22

Hopefully you are able to change the server encoding of the JSON to UTF-8.

If not, you can resolve this issue by replacing the default JSON mime type handler in Restkit. Use the Restkit class RKNSJSONSerialization as reference.

In your custom JSON mime type handler, perform data conversion from the incoming encoding (in the example below ISO-8859-1) to UTF-8, before doing the same as the RKNSJSONSerialization class.

@implementation MyCustomJSONSerializer    

+ (id)objectFromData:(NSData *)data error:(NSError **)error
{
    NSString* latin = [[NSString alloc] initWithBytes:[data bytes] length:[data length] encoding:NSISOLatin1StringEncoding];

    NSData* utf8 = [latin dataUsingEncoding:NSUTF8StringEncoding];

    return [NSJSONSerialization JSONObjectWithData:utf8 options:0 error:error];
}

@end

You can do similar for the dataFromObject method if you must POST data back to the server in non-UTF-8 encoding.

You can now add this custom handler after you init Restkit, and it will be used vs the default (UTF-8) one:

[RKMIMETypeSerialization registerClass:[MyCustomJSONSerializer class] forMIMEType:RKMIMETypeJSON];
查看更多
放我归山
3楼-- · 2019-07-23 16:47

This kind of error comes from JSON mapping under RK. Default is to use NSJSONSerialization encapsulated in RKNSJSONSerialization. You can put a breakpoint there to find out maybe more about the error. I found 2 sources until now:

  • NSJSONSerialization doesn't like non UTF8 data. Make sure you either receive it from server, or modify RK to do the proper conversion from data to string(with correct encoding) to UTF8-data(best way i have so far). If using CoreData you can look in RKManagedObjectRequestOperation at line 586.
  • in iOS5 there are bugs. Easiest fix is to use another parsing library
查看更多
登录 后发表回答