get JSON file or info from AFNetworking - ios

I have piece of good working code that downloads and parses JSON from server and returns result in +JSONRequestOperationWithRequest:success:failure: of AFJSONRequestOperation. success (and also failure)part of method takes block as an argument with id JSON argument in it. If I understand right - this object is for representation of JSON file or it's content. I need to have a possibility to send this JSON file (or it's text representation in every other text format) to email, using MFMailComposeViewController. So, two questions:
how can I get this JSON content from this file?
do I need register .json filetype to have possibility to send it using MFMailComposeViewController?

how can I get this JSON content from this file?
You can get the JSON data response (before it's converted to Foundation objects by NSJSONSerialization) from
operation.responseString (as NSString), or
operation.responseData (as NSData).
You'll want the latter if you're going to attach it to an e-mail.
do I need register .json filetype to have possibility to send it using
MFMailComposeViewController?
You need to call [MFMailComposeViewController -addAttachmentData:mimeType:fileName:]. You can get the mime-type from the operation.response.allHeaderFields NSDictionary. You can also use the official standard, application/json, or text/json, which is commonly used as well.

The response in the succes if not JSON but the object representation of the JSON. Most likely a NSArray or NSDictionary.
What you need to do is either use a normal HTTP request and send that string to the MFMailComposeViewController or change the JSON object back into a JSON string:
NSError *error = nil;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:JSON options:0 error:&error];
NSString *jsonString = nil;
if (jsonData) {
jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
} else {
NSLog(#"Error creating JSON: %#", error);
}
Then you can pass the jsonString in your MFMailComposeViewController.

Related

backslashes "\" added in JSON string for web service in swift

In my project I need to send JSON object in web service API call. I have converted JSON from array.
do {
let theJSONData = try NSJSONSerialization.dataWithJSONObject(
param ,
options: NSJSONWritingOptions(rawValue: 0))
var theJSONText : String = String(data: theJSONData,
encoding: NSASCIIStringEncoding)!
print(theJSONText)
theJSONText = theJSONText.stringByReplacingOccurrencesOfString("\\", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
print(theJSONText)
let newParam = ["ESignData":theJSONText]
} catch let error as NSError {
print(error)
}
it print string correctly as
{"EntNum":"47","JobNo":"1737753","ClientID":"100","HospNo":"1","QAReason":"","DoctorNo":"1694","Action":"Sign"}
{"EntNum":"47","JobNo":"1737753","ClientID":"100","HospNo":"1","QAReason":"","DoctorNo":"1694","Action":"Sign"}
Now When I try to send this newParam dictionary in API call, it contains "\" in string parameters of JSON string.
WebService.PostURL(mainLink, methodname: ESIGNTHISDOC, param: newParam, userName: AUTH_USERNAME, password: AUTH_PWD, CompletionHandler: { (success, response) in
})
And in that web service method I have print param.
Param = {
ESignData = "{\"EntNum\":\"47\",\"JobNo\":\"1737753\",\"ClientID\":\"100\",\"HospNo\":\"1\",\"QAReason\":\"\",\"DoctorNo\":\"1694\",\"Action\":\"Sign\"}";
}
Now in this I know it is obvious in iOS because of " in string. Now the problem is that there are lots of APIs working in android app, and the API developer doesn't want to update his code according to us.
I know this problem happens because of adding JSON string in dictionary as parameter. But I have not proper justification for that so if any proof will be also helpful for me to convince him.
Any solution to convert the JSON string without backslash in iOS? I need to fix from my side if possible. Any help will be appreciate.
EDIT :
On server side it needs like
ESignData = {"EntNum":"47","JobNo":"1737753","ClientID":"100","HospNo":"1","QAReason":"","DoctorNo":"1694","Action":"Sign"}
If I pass this as parameter in POSTMAN than it gives success message. But not with our object with "\" in it.
EDIT 2:
Now printing the newParam dictionary:
print(newParam)
print("-------------------------")
print(newParam["ESignData"])
And logs :
["ESignData": "{\"EntNum\":\"47\",\"JobNo\":\"1737754\",\"ClientID\":\"100\",\"HospNo\":\"1\",\"QAReason\":\"\",\"DoctorNo\":\"1694\",\"Action\":\"Sign\"}"]
-------------------------
Optional("{\"EntNum\":\"47\",\"JobNo\":\"1737754\",\"ClientID\":\"100\",\"HospNo\":\"1\",\"QAReason\":\"\",\"DoctorNo\":\"1694\",\"Action\":\"Sign\"}")
And by debug :
Printing description of newParam:
▿ 1 elements
▿ [0] : 2 elements
- .0 : "ESignData"
- .1 : "{\"EntNum\":\"47\",\"JobNo\":\"1737754\",\"ClientID\":\"100\",\"HospNo\":\"1\",\"QAReason\":\"\",\"DoctorNo\":\"1694\",\"Action\":\"Sign\"}"
So it shows that it is in our dictionary. All the " are joined by \.
I ran into this exact issue today. For me it appears that the default encoding for any NSURLRequest is a string. So, somewhere between my creating the dictionary request and the server parsing it, the backslashes would appear and the server had problems with my payload.
I solved the issue by explicitly stating that my payload was JSON by setting the content type header.
[authRequest setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
Now when I create JSON data from a dictionary, the backslashes don't appear and the server is able to parse everything correctly.
Code snippet below for completeness:
NSMutableURLRequest *authRequest = [[[NSURLRequest alloc] initWithURL:authURL] mutableCopy];
[authRequest setHTTPMethod:#"POST"];
NSURLSession *session = [NSURLSession sharedSession];
[authRequest setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
NSDictionary *bodyDictionary = #{#"User_Name": user, #"Password_Hash": password};
if ([NSJSONSerialization isValidJSONObject:bodyDictionary]) {
NSError *error;
NSData *bodyData = [NSJSONSerialization dataWithJSONObject:bodyDictionary options:0 error:&error];
if (!error) {
[authRequest setHTTPBody:bodyData];
} else {
NSLog(#"Unable to convert to JSON DATA %#", error.localizedDescription);
}
}

How can I read and decrypt the file in iOS if it is an XML file and trying to store it in NSString to decrypt it?

NSString* pathss = [[NSBundle mainBundle] pathForResource:#"documentary" ofType:#"xml"];
NSString* contents = [NSString stringWithContentsOfFile:pathss encoding:NSUTF8StringEncoding error:NULL];
NSLog(#"content of file is: %#",contents);
It displays only the word "U", at the place of contents.
For a comment by the OP: "it is AES encrypted xml file"
If the XML file is AES encrypted it is comprised of data bytes, not characters and can not be represented as a UTF-8 string nor any string encoding in a useful way.
It is necessary to read the file into an NSData, not an NSString. AES decryption expects data, not a string as input and returns data as output. Since the original input to AES was a valid XML string (as data) the resultant output data can then be decoded to the original XML string.
if (pathss == nil) {
NSLog(#"pathss is nil");
// Handle error
}
NSError *error;
NSData *encryptedXML = [NSData dataWithContentsOfFile: pathss options:0 error:&error];
if (encryptedXML == nil) {
NSLog(#"Data read error: %#", error);
// Handle error
}
else {
// decrypt encryptedXML
}
Don't ignore the error handling and the error parameter, it will provide information about any error.
Decrypting the encryptedXML will require the encryption key, the encryption mode , padding option and possibly an iv (initialization vector).

Get JSON string for my object with RestKit

I want to create a json string to save in NSUserDefaults and then get it back from it.
I've already added RestKit to my project, to send and receive objects from the server.
However, now i want to flatten and save the data.
How do i use restkit to get a JSON string of my object?
I needed the same functionality (in my case to send he JSON as a multipart attribute), so after a while searching, I get the solution.
You can get the JSON data (and JSON string) using RestKit with that code, you have to pass the object you want to convert, and the mapping you want to use to convert.
RKRequestDescriptor *descriptorObject = ...
Custom *object = ...
NSDictionary *parametersForObject = [RKObjectParameterization parametersWithObject:object requestDescriptor:descriptorObject error:nil];
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:parametersForObject
options:NSJSONWritingPrettyPrinted //Pass 0 if you don't care about the readability of the generated string
error:&error];
NSString *jsonString;
if (! jsonData) {
NSLog(#"Got an error: %#", error);
}
else {
jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
}
I have not find this documented, I just find it browsing the code, I am not sure if it is a public API or a private one. At least, it works for RestKit 0.20
You generally don't. RestKit serialises to JSON only as part of a network communication. In this case you're converting from an internal to external data format. In your case you want an internal data format stored for a while. In this case it's easier to just use NSJSONSerialization. To do this you do need to create a dictionary / array and then use dataWithJSONObject:options:error:.
Technically, to do what you ask you would use RKMappingOperation. This is done using the initWithSourceObject:destinationObject:mapping:, where the source object is the dictionary created from the JSON (JSONObjectWithData), the destination object is a new instance of the object targeted by the mapping and the mapping is your mapping to use.

Working with AES encryption in IOS

I am getting problem while encryption.
The server is sending json data which is aes256 encrypted and then base64 encoded.
while in the ios client side i am able to get the response and decode it using base64.
The AES256 decryption works on some libraries(3rd party or wrappers aroound CommonCryptor.h) and not working in another.
When decryption is working the parsing is not working.
The following are the wrappers libraries and the respective code.
RNCryptor
(https://github.com/rnapier/RNCryptor)
NSData *decodedData = [Util decode:data];
NSData *RNDecryptedData = [RNDecryptor decryptData:decodedData withPassword:randomString error:&error];
if (error == nil) {
NSLog(#"RNDecryptedData - %#",[Util hexStringFromData:RNDecryptedData]);
response = [NSJSONSerialization JSONObjectWithData:RNDecryptedData options:NSJSONReadingMutableContainers error:&error];
NSLog(#"response - %#",response);
NSLog(#"error1 - %#",error);
} else
NSLog(#"error2 - %#",error);
I am getting following error while decryption.
EncryptedParsing[4402:70b] error2 - Error Domain=net.robnapier.RNCryptManager Code=2 "Unknown header" UserInfo=0x8c6bd60 {NSLocalizedDescription=Unknown header}
CCrypto
(https://github.com/Gurpartap/AESCrypt-ObjC)
NSData *decodedData = [Util decode:data];
NSData *CCDecryptedData = [decodedData decryptedAES256DataUsingKey:randomString error:&error];
if (error == nil) {
response = [NSJSONSerialization JSONObjectWithData:CCDecryptedData options:NSJSONReadingMutableContainers error:&error];
NSLog(#"response - %#",response);
NSLog(#"error1 - %#",error);
} else
NSLog(#"error2 - %#",error);
Here I am getting the decrypted data, but while parsing it is giving following error
EncryptedParsing[4469:70b] error1 - Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (JSON text did not start with array or object and option to allow fragments not set.) UserInfo=0x8a51520 {NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}
NSData+AES256
(http://pastie.org/426530)
NSData *decodedData = [Util decode:data];
NSData *AES256DecryptedData = [decodedData AES256DecryptWithKey:randomString];
response = [NSJSONSerialization JSONObjectWithData:AES256DecryptedData options:NSJSONReadingMutableLeaves error:&error];
NSLog(#"error - %#",error);
I am getting the decryption data, while parsing i am getting following error
EncryptedParsing[4646:70b] error - Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (JSON text did not start with array or object and option to allow fragments not set.) UserInfo=0x8a710c0 {NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}
Along with these I have also used CocoaSecurity (https://github.com/kelp404/CocoaSecurity)
But it is not working.
I am using NSData+Base64 (https://github.com/l4u/NSData-Base64) for base64 decoding
By the way there is no problem from server side(we tested it).
I want to know the error i am doing. Or is there any other way to achieve it
There is no universal standard way to encode AES encrypted data. You need agreement on both sides about how to encode the various metadata required.
RNCryptor is failing to decrypt because it expects the data to be in the RNCryptor format.
CCCrypto and AES256DecryptWithKey are probably interpreting the key differently than you intend. Neither verifies that the key you pass is correct, so you likely are getting garbage back. If that's the case, I would expect that for some messages you get garbage back, and for other messages you get nothing back, or an error.
RNCryptor has implementations in several languages if you need a cross-platform solution. If you are required to conform to a server format (which is likely not secure encryption from the looks of your code), then you'll need to provide the server code in order to determine the correct client code.
try to replace NSJSONReadingMutableLeaves with kNilOptions.

How to get the response data out of the NSHTTPURLResponse in the callback of AFJSONRequestOperation?

I have a situation where I need to access the raw response data for an AFJSONRequestOperation, from within the callback block which includes only NSHTTPURLResponse. I am able to get the statusCode from the NSHTTPURLResponse, but don't see any way to get to the raw data. Is there a good way that anyone knows of to access this from the failure callback block of this operation?
NSHTTPURLResponse only contains HTTP header information; no body data. So no, this would be impossible. If you have any control over this code, have the block or method pass the operation itself and get responseData or responseJSON.
In the callback from responseJSON you can get the body from a DataResponse<Any> object using response.result.value or String(data:response.data!, encoding: .utf8).
You can't get it from response.response, which is a NSHTTPURLResponse object. This only has header info.
Alamofire.request(URL(string: "https://foo.com")!).validate(statusCode: 200..<300).responseJSON() { response in
let body = response.result.value
}
If the http response doesn't validate the above doesn't work. but this does:
Alamofire.request(URL(string: "https://foo.com")!).validate(statusCode: 200..<300).responseJSON() { response in
let body = String(data:response.data!, encoding: .utf8)
}
Old question, but anyway...
You don't need to get to the operation object, you can easily do something like:
NSData * data = [NSJSONSerialization dataWithJSONObject:JSON options:0 error:nil]];
With the JSON id that the callback receives.

Resources