Reputation: 9869
can one AFTHTTPClient handle both json and xml?
I have one single domain in which some services only return json, while others only return xml. How would I make a GET request and instruct AFHTTPClient to use AFJSONRequestOperation for some services and an AFXMLRequestOperation for other GET requests?
So what I would like is:
chairs.com GET customerprofile ---> returns XML (no option for json)
charis.com GET inventory ---> returns JSON (no option for xml)
Is this a job for multiple AFHTTPClients? Thanks
Upvotes: 2
Views: 1278
Reputation: 66242
Your use of AFHTTPClient
indicates you're using AFNetworking 1, but I'll answer this question for both versions, for future readers.
You just need to register the appropriate AFHTTPOperation subclass. This is typically done in your subclass of initWithBaseURL:
:
- (instancetype) initWithBaseURL:(NSURL *)url {
self = [super initWithBaseURL:url];
if (self) {
[self registerHTTPOperationClass:[AFJSONRequestOperation class]];
[self registerHTTPOperationClass:[AFXMLRequestOperation class]];
}
return self;
}
When your app makes an outgoing request, you'll need to make sure your accept
headers are set appropriately (for example, to text/json
or text/xml
, depending on what you expect from which endpoint you hit). Otherwise, AFNetworking won't know which operation to use for which request.
There are a few ways to easily solve this Accept
header requirement. If one of your endpoints is an exception to a general rule, I might do this by overriding requestWithMethod:path:parameters:
:
- (NSMutableURLRequest *)requestWithMethod:(NSString *)method
path:(NSString *)path
parameters:(NSDictionary *)parameters {
request = [super requestWithMethod:method path:path parameters:parameters];
if (/* the endpoint specified in path returns XML */) {
[request setValue:@"text/xml" forHTTPHeaderField:@"Accept"];
} else {
[request setValue:@"text/json" forHTTPHeaderField:@"Accept"];
}
}
This is a small violation of tell, don't ask; feel free to refactor as necessary.
If you don't plan on upgrading to AFNetworking 2, then you can stop reading here.
Version 2.0 of AFNetworking makes this simpler and more intuitive. In 2.0, the serialization responsibility is broken out into a separate class. Instances of this class are called response serializers. When you upgrade, you'll want an AFCompoundResponseSerializer. The documentation describes it best:
AFCompoundSerializer
is a subclass ofAFHTTPSerializer
that delegates the response serialization to the firstAFHTTPSerializer
object that returnsYES
tovalidateResponse:data:error:
, falling back on the default behavior ofAFHTTPSerializer
. This is useful for supporting multiple potential types and structures of server responses with a single serializer.
For example:
AFJSONResponseSerializer *jsonSerializer = [AFJSONResponseSerializer serializerWithReadingOptions:0];
AFXMLDocumentSerializer *xmlSerializer = [AFXMLDocumentSerializer serializerWithXMLDocumentOptions:0];
AFCompoundResponseSerializer *compoundSerializer = [AFCompoundResponseSerializer compoundSerializerWithResponseSerializers:@[jsonSerializer, xmlSerializer]];
[AFHTTPSessionManager manager].responseSerializer = compoundSerializer;
Upvotes: 7