13

i am writing an ios app that uses restkit to communicate with a web server through Rest with JSON

i am able to use [[RKObjectManager sharedManager] loadObjectsAtResourcePath:path delegate:self] to get object from my web service as JSON, map it to obj-c object, it works fine

now i am trying to use: [[RKObjectManager sharedManager] putObject:obj delegate:self]; and this call sends an object to the web service as form encoded and not JSON

so my question is: how to configure the sharedManager (or the routeur?) to send with content type JSON instead of form encoded.

any code example much appreciated.

Thx!

benzado
  • 82,288
  • 22
  • 110
  • 138
goane
  • 311
  • 1
  • 3
  • 6

5 Answers5

9

The easiest way is to simply set the property when you initialize the object manager, like so:

RKObjectManager* objectManager = [RKObjectManager objectManagerWithBaseURL:@"http://url.com"];
objectManager.serializationMIMEType = RKMIMETypeJSON;
Evan Cordell
  • 4,108
  • 2
  • 31
  • 47
  • This is the only way to do it on the newer versions. – Chris Ballinger Oct 12 '11 at 23:10
  • 9
    as of RestKit v0.20 use `objectManager.requestSerializationMIMEType = RKMIMETypeJSON;` – Ric Santos Feb 26 '13 at 04:56
  • 1
    When using `[objectManager postObject:path:parameters...]` the content-type header was not being set to "application/json" even after I set the requestSerializationMIMEType. I ended up adding `[[objectManager HTTPClient] setDefaultHeader:@"content-type" value:RKMIMETypeJSON];` and it started working properly. – Wolfsokta Nov 17 '13 at 07:18
3

Evan is correct, but I've had to also make sure I am sending a JSON string, because I had a nested NSDictionay.

If you have a dictionary you want to send as a JSON string, here's how you can do it:

// create a JSON string from your NSDictionary
NSError *error; 
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict 
                                                   options:NSJSONWritingPrettyPrinted // Pass 0 if you don't care about the readability of the generated string
                                                     error:&error];
NSString *jsonString = [[NSString alloc] init];
if (!jsonData) {
    NSLog(@"Got an error: %@", error);
} else {
    jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
}

// make the post using the objectManager if you want to map the response to a model
RKObjectManager* objectManager = [RKObjectManager sharedManager];  
[objectManager loadObjectsAtResourcePath:@"/api/" delegate:self block:^(RKObjectLoader* loader) {
    loader.serializationMIMEType = RKMIMETypeJSON; // We want to send this request as JSON
    loader.objectMapping = [objectManager.mappingProvider objectMappingForClass:[Plan class]];
    loader.resourcePath = @"/api/";
    loader.method = RKRequestMethodPOST;
    loader.params = [RKRequestSerialization serializationWithData:[jsonString dataUsingEncoding:NSUTF8StringEncoding] MIMEType:RKMIMETypeJSON];
}];
Flaviu
  • 6,240
  • 4
  • 35
  • 33
  • I'm glad you found a solution that works, but you're sort of putting a square peg in a round hole. Check out the `postObject:path:parameters:success:failure:` method on RKObjectManager. You can just put your NSDictionary as the `postObject:` parameter and RestKit will handle the serialization (no need to define mappings - it's just a dictionary). – Evan Cordell Aug 16 '13 at 20:19
1

Create an Object Manager and set the property for matching the header in JSON format

RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://mobile.com"]];
[objectManager addResponseDescriptorsFromArray:@[responseDescriptor]];

objectManager.requestSerializationMIMEType = RKMIMETypeJSON;
Jesús Hurtado
  • 295
  • 2
  • 12
1

Okay just found how to do it:

subclass RKRouter.h or just change in RKDynamicRouter.m

return [object propertiesForSerialization];

to

[RKJSONSerialization JSONSerializationWithObject:[object propertiesForSerialization]];

and RestKit generate JSON for putObject call

Darren
  • 68,902
  • 24
  • 138
  • 144
goane
  • 311
  • 1
  • 3
  • 6
  • Hmmm can you be a bit more explicit? I am a RestKit beginner and I don't get it: 1- RKRouter.h defines a protocol. What do you mean "subclassing" it? 2- Which function do you implement/override? 3- Where and how do you instantiate this new Router class? – Jean-Denis Muys Apr 28 '11 at 13:34
0

You can change serializationMIMEType for individual requests by subclassing RKObjectManager and change implementation of requestWithObject:method:path:parameters: in subclassed manager.

Send request:

SubclassedObjectManager *manager = ...
[manager putObject:nil
           path:pathString
     parameters:parameters
        success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
      } failure:^(RKObjectRequestOperation *operation, NSError *error) {
      }
 ];

Modify MIMEType of request for PUT method:

- (NSMutableURLRequest *)requestWithObject:(id)object method:(RKRequestMethod)method path:(NSString *)path parameters:(NSDictionary *)parameters
{
  NSMutableURLRequest *request = [super requestWithObject:object method:method path:path parameters:parameters];
  if (method&RKRequestMethodPUT) {
    NSError *error = nil;
    NSData *serializedJSON = [RKMIMETypeSerialization dataFromObject:parameters MIMEType:RKMIMETypeJSON error:&error];
    [request setValue:RKMIMETypeJSON forHTTPHeaderField:@"Content-Type"];
    [request setHTTPBody:serializedJSON];
  }

  return request;
}
FunkyKat
  • 3,233
  • 1
  • 23
  • 20