I'm trying to use a service of DocuSign API in an objective C project. This link shows what data I've to add to body but I'm still starting with objective C development and I can't know how do it.
I tried the following but I received nil data
NSDictionary *EnvelopesStatusRequestData = #{#"envelopeIds": envelopesPending};
where envelopesPending is an array that I fill with envelopesId that I have in a DDBB.
NSMutableArray *envelopesPending = [NSMutableArray array];
This is the code that I use to call service API:
NSDictionary *authenticationHeader = #{ #"Username": email, #"Password" : password, #"IntegratorKey" : integratorKey };
NSDictionary *EnvelopesStatusRequestData = #{#"envelopeIds": envelopesPending};
NSData* dataStatus = [[self jsonStringFromObject:EnvelopesStatusRequestData] dataUsingEncoding:NSUTF8StringEncoding];
NSString *envelopesURL = [NSMutableString stringWithFormat:#"%#/envelopes/status",baseUrl];
NSMutableURLRequest *envelopeRequest = [self initializeRequest:envelopesURL setMethod:#"GET" setBody:dataStatus];
[envelopeRequest setValue:[self jsonStringFromObject:authenticationHeader] forHTTPHeaderField:#"X-DocuSign-Authentication"];
[envelopeRequest setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
NSURLResponse *envelopesResponse = nil;
NSError *envelopesError = nil;
NSData *envelopeData = [NSURLConnection sendSynchronousRequest:envelopeRequest returningResponse:&envelopesResponse error:&envelopesError];
EDIT:
The error was that is a PUT method, so the request is:
NSMutableURLRequest *envelopeRequest = [self initializeRequest:envelopesURL setMethod:#"PUT" setBody:dataStatus];
With this change I have an error that says:
errorCode = "INVALID_REQUEST_PARAMETER";
message = "The request contained at least one invalid parameter. Query parameter 'from_date' must be set to a valid DateTime, or 'envelope_ids' or 'transaction_ids' must be specified.";
This error is solved adding the envelope_ids parameter to request:
PUT https://{server}/restapi/{apiVersion}/accounts/{accountId}/envelopes/status?envelope_ids=request_body
I pass the dictionary to a string with this code:
NSData *dataEnv = [NSJSONSerialization dataWithJSONObject:envelopesPending options:NSJSONReadingMutableLeaves error:&error];
NSString *querystring = [[NSString alloc] initWithData:dataEnv encoding:NSUTF8StringEncoding];
querystring = [querystring stringByReplacingOccurrencesOfString:#"[" withString:#""];
querystring = [querystring stringByReplacingOccurrencesOfString:#"]" withString:#""];
querystring = [querystring stringByReplacingOccurrencesOfString:#"\"" withString:#""];
NSString *envelopesURL = [NSMutableString stringWithFormat:#"%#/envelopes/status?envelope_ids=%#",baseUrl, querystring];
It looks like you've figured this out, but basically here are the details of the REST API call you need to make:
Get Envelope Status for more than One Envelope
This returns envelope status for the requested envelopes.
URL:
/accounts/{accountId}/envelopes/status
Formats:
XML, JSON
HTTP Method:
PUT
Required URL Parameter:
?envelope_ids=request_body
Request Body:
{
"envelopeIds":[
"String content",
"String content"
],
}
So a sample request would look like:
PUT https://{server}/restapi/{apiVersion}/accounts/{accountId}/envelopes/status?envelope_ids=request_body
X-DocuSign-Authentication: <DocuSignCredentials><Username>{name}</Username><Password>{password}</Password><IntegratorKey>{integrator_key}</IntegratorKey></DocuSignCredentials>
Accept: application/json
Content-Type: application/json
{
"envelopeIds":[
"12af49cd-....................",
"b342c324-...................."
],
}
The error was that is a PUT method, so the request is:
NSMutableURLRequest *envelopeRequest = [self initializeRequest:envelopesURL setMethod:#"PUT" setBody:dataStatus];
With this change I have an error that says:
errorCode = "INVALID_REQUEST_PARAMETER"; message = "The request contained at least one invalid parameter. Query parameter 'from_date' must be set to a valid DateTime, or 'envelope_ids' or 'transaction_ids' must be specified.";
This error is solved adding the envelope_ids parameter to request:
PUT https://{server}/restapi/{apiVersion}/accounts/{accountId}/envelopes/status?envelope_ids=request_body
I pass the dictionary to a string with this code:
NSData *dataEnv = [NSJSONSerialization dataWithJSONObject:envelopesPending options:NSJSONReadingMutableLeaves error:&error];
NSString *querystring = [[NSString alloc] initWithData:dataEnv encoding:NSUTF8StringEncoding];
querystring = [querystring stringByReplacingOccurrencesOfString:#"[" withString:#""];
querystring = [querystring stringByReplacingOccurrencesOfString:#"]" withString:#""];
querystring = [querystring stringByReplacingOccurrencesOfString:#"\"" withString:#""];
NSString *envelopesURL = [NSMutableString stringWithFormat:#"%#/envelopes/status?envelope_ids=%#",baseUrl, querystring];
Related
I have an application in which I am having a json response like this.
{"success":"true","message":"You have logged in","pserial":"1"} and I am separating with ":".
And I am getting data like this pSerial:"1"} but I want only 1 value.
NSURL *url = [NSURL URLWithString:strUrl];
NSData *respData = [NSData dataWithContentsOfURL:url];
NSString *strResp = [[NSString alloc]initWithData:respData encoding:NSUTF8StringEncoding];
NSString *approvalString = [[strResp componentsSeparatedByString:#":"] objectAtIndex:3];
NSLog(#"pSerial:%#",approvalString);
for Example :
SBJsonParser *jsonPar = [[SBJsonParser alloc] init];
NSError *error = nil;
NSArray *jsonObj = [jsonPar objectWithString:jsonString error:&error];
id jsonObj = [jsonPar objectWithString:jsonString error:&error];
if ([jsonObj isKindOfClass:[NSDictionary class]])
// treat as a dictionary, or reassign to a dictionary ivar
else if ([jsonObj isKindOfClass:[NSArray class]])
// treat as an array or reassign to an array ivar.
Then get the value :
NSMutableArrary *userMutArr = [NSMutableArray array];
for (NSDictionary *dict in jsonObj)
{
User *userObj = [[[User alloc] init] autorelease];
[userObj setFirstName:[dict objectForKey:#"firstName"]];
[userObj setLastName:[dict objectForKey:#"lastName"]];
[userObj setAge:[[dict objectForKey:#"age"] intValue]];
[userObj setAddress:[dict objectForKey:#"address"]];
[userObj setPhoneNumbers:[dict objectForKey:#"phoneNumber"]];
[userMutArr addObject:userObj];
}
Hope you will understand. and read some Documents. it will help you.
It looks like you are in need of JSON Parsing. Here, what you want is JSON Parsing, not separating data from the JSON Response. JSON is the format of the data in which data is formatted in Key-Value pairs. You can fetch the "Value" of any object using the "Key".
Your first two lines are correct.
NSURL *url = [NSURL URLWithString:strUrl];
NSData *respData = [NSData dataWithContentsOfURL:url];
Now, you can parse JSON Response like this :
NSError* error;
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:respData options:kNilOptions error:&error];
NSString *pSerial = [json objectForKey:#"pserial"];
This will give you the value of "pserial" from your response. Similarly, you can get the values for "success" and "message". You can check it using this line :
NSLog(#"pserial :: %#",pserial);
You need to parse the JSON Response String, you can use any JSON parser like:
https://github.com/stig/json-framework/
And in your code do:
NSString *strResp = [[NSString alloc]initWithData:respData encoding:NSUTF8StringEncoding];
NSDictionary *ResponseDictionary = [strResp JSONValue];
NSString * pSerial = (NSString*)[ResponseDictionary objectForKey:#"pserial"];
Dont separation by ":" just use JSONValue your response is like
// {"success":"true","message":"You have logged in","pserial":"1"}
// with SBJsonParser parse your object like this
NSDictionary *responseJson = [YOUR-OBJECT JSONValue];
Note: dont forget to add Json header file
Its better you use any OpenSource Json Parser
Here is a stack post Comparison of different Json Parser for iOS
EDIT 2: I no longer think "_" and "/" in the dictionary keys are the problem.
EDIT 3: I don't think the JSON is the problem any more, or the HTTP POST request. I don't know exactly what it is yet.
EDIT 4: Solved it. The data element had to be valid base64, or else couch refuses it. Didn't know that. Can't select my own answer yet.
I have a dictionary I want to convert to a JSON string.
This is the setup of my dictionary:
- (NSDictionary*) createDictionary
{
NSMutableDictionary *room = [[NSMutableDictionary alloc] init];
[room setObject:self.roomNumber forKey:#"roomNumber"];
[room setObject:self.floor forKey:#"floor"];
[room setObject:self.comment forKey:#"comment"];
[room setObject:self.type forKey:#"type"];
[room setObject:[NSNumber numberWithInt:self.status] forKey:#"status"];
[room setObject:[[NSMutableDictionary alloc] init] forKey:#"_attachments"];
NSMutableDictionary *attachments = [room objectForKey:[NSString stringWithFormat:#"_%#", #"attachments"]];
[attachments setObject:[[NSMutableDictionary alloc] init] forKey:#"picture"];
NSMutableDictionary *picture = [attachments objectForKey:#"picture"];
[picture setObject:#"text/plain" forKey:#"content_type"];
[picture setObject:#"BASE64" forKey:#"data"];
NSLog(#"Room: %#", room);
return room;
}
The problem is the "_" and "/" chars. When I print out the dictionary, it looks like this:
Room: {
"_attachments" = {
picture = {
"content_type" = "text/plain";
data = BASE64;
};
};
comment = 12;
floor = 12;
roomNumber = 12;
status = 0;
type = room;
}
Don't know why it ends up on one line there, but anyway, thats not important. The thing is that the keys with "_" or "/" ends up surrounded with "-marks, and my web endpoint receiving JSON can't read it. Does anyone know how I can solve this? I use couchdb and need the _ in from of the attachments key.
EDIT: I am using it, I pass my dictionary to NSJSONSerialization, calling the function dataWithJSONObject:options:error:. I store what I get from that function in a NSData object, and set it as the http body in the request I make. Content-Type is application/json. I also set the Content-length etc. Here is the function that makes the HTTP request. createDictionary is the function above.
// Make a JSON object from the dictionary
NSError *err;
NSData* jsonRoom = [NSJSONSerialization dataWithJSONObject:[room createDictionary]
options:NSJSONWritingPrettyPrinted
error:&err];
// Set up the http POST request
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]
initWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#%#", _baseURL, #"/peters_hotell"]]];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setValue:[NSString stringWithFormat:#"%d", [jsonRoom length]]
forHTTPHeaderField:#"Content-length"];
[request setHTTPBody:jsonRoom];
NSLog(#"%#", jsonRoom);
// Fire the http POST request
//[NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:callback];`
Right now the sendRequest call is commented out, but when I use it, the server can't accept the request.
This is the response from couchdb:
Data: {
error = badmatch;
reason = false;
}
When I leave the attachments part out of the dictionary, couch does not complain. Basically what I am trying to create is this JSON (inline attachment): http://wiki.apache.org/couchdb/HTTP_Document_API#Inline_Attachments
The thing is that the keys [...] end up being surrounded with quotation marks, and my web endpoint receiving JSON can't read it.
No, it's the opposite: what you think is JSON isn't really JSON. JSON requires the keys to be quoted, it separates keys and values using colons (:) and not an equal sign, etc.
What you currently print out is the description of the NSDictionary object and it is not JSON. It's in the legacy NeXTSTEP-style property list format.
What you want to use is the NSJSONSerialization class.
When you are posting the url and Json Object, before posting it to server encode the URL string using the
stringByAddingPercentEscapesUsingEncoding
or
NSUTF8Encoding technique..
Thanks for the help! It led me to the answer. As it turns out, my POST request was refused because my data entry wasn't valid base64, so couch refused it.
Code:
#implementation NSString (NSString_Extended)
- (NSString *)urlEncoded
{
CFStringRef urlString = CFURLCreateStringByAddingPercentEscapes(
NULL,
(CFStringRef)self,
NULL,
(CFStringRef)#"!*'\"();:#&=+$,/?%#[]% ",
kCFStringEncodingUTF8 );
return [(NSString *)urlString autorelease];
}
#end
I have to connect to a URL to check whether the records is empty. The response looks something like this:
<?xml version = "1.0" encoding = "UTF-8"?>
<find>
<record_id>1234</record_id>
<no_record>00001</no_record>
<entry_num>00001</entry_num>
<session-id>aijheifaohqrihelrkqn324tlejaofjaf</session-id>
</find>
My codes:
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init]
autorelease];
[request setURL:[NSURL URLWithString: finalSearchURL]];
// Content-Type related.
[request setValue:#"application/x-www-form-urlencoded"
forHTTPHeaderField:#"Content-Type"];
// Create Connection.
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
if (conn) {
// The connection was established.
NSMutableData *receivedData = [[NSMutableData alloc] initWithContentsOfURL:[NSURL URLWithString:request]];
NSLog( #"Data will be received from URL: %#", request.URL );
NSLog(#"Recieved Data 2: %#", receivedData);
}
else
{
// The download could not be made.
NSLog( #"Data could not be received from: %#", request.URL );
}
But it returns me:
Recieved Data : <3c3f786d 6c207665 7273696f 6e203d20 22312e30 2220656e 636f6469 6e67203d 20225554 462d3822 3f3e0a3c 66696e64 3e0a3c73 65745f6e 756d6265 723e3031 39303633 3c2f7365 745f6e75 6d626572 3e0a3c6e 6f5f7265 636f7264 733e3030 30303030 3030313c 2f6e6f5f 7265636f 7264733e 0a3c6e6f 5f656e74 72696573 3e303030 30303030 30313c2f 6e6f5f65 6e747269 65733e0a 3c736573 73696f6e 2d69643e 4d505843 33323433 58564336 4534454a 41464232 45473541 39374237 584e3832 43554631 4e314234 584e4c37 424c5947 4e533c2f 73657373 696f6e2d 69643e0a 3c2f6669 6e643e0a 20>
Can anyone help to tell me what am I doing wrong? This is my first attempt for getting response from a url please help thanks!
See the data as a string this way:
NSString *string = [[NSString alloc] initWithData:receivedData encoding:NSUTF8StringEncoding];
NSLog(#"the xml string is %#", string);
If the parsing goal is simple enough - like just to find the value of one tag - you can use string methods to parse. Otherwise, NSXMLParser or several other options are available.
To see if the string contains a substring, you can do something like this:
if (string) {
NSRange range = [string rangeOfString:#"<session-id>"];
if (range.location != NSNotFound) {
// session-id tag is at index range.location, so we know it's there
}
}
The method you used is to get the raw data from the url. You need a parser to convert the raw data to the understandable structure (probably NSDictionary rather than NSArray).
Apple has provided NSXMLParser for you to retrieve the xml structure from the url or you can find other xml parser libraries.
Actually, your code is returning the correct data. Since NSData can hold any kind of data, it will just display the hex value. If you convert the hex data to a sting, you'll see that it has the correct text.
Now, your code can be simplified a lot. All the code for setting up the NSURLConnection is not needed at all. All you need is the following line.
NSString *recievedText = [NSString stringWithContentsOfFile:finalSearchURL encoding:NSUTF8StringEncoding error:NULL];
I have the following response from server side:
{"_playLists":[{"name":"Playlist 1","items":[{"name":"Poza 1","target":"http:\/\/myaudi.fr","url":"http:\/\/test.res-novae.fr\/sfrplay\/upload\/image\/pic1_iphone3.jpg","url_thumb":"http:\/\/test.res-novae.fr\/sfrplay\/upload\/thumb\/pic1_iphone3_thumb.jpg"},{"name":"Poza 2","target":"http:\/\/audifrance.fr","url":"http:\/\/test.res-novae.fr\/sfrplay\/upload\/image\/pic2_iphone3.jpg","url_thumb":"http:\/\/test.res-novae.fr\/sfrplay\/upload\/thumb\/pic2_iphone3_thumb.jpg"}]},{"name":"Playlist 2","items":[{"name":"Poza 3","target":"http:\/\/google.ro","url":null,"url_thumb":null}]}]}
And I'm trying to acces this by using:
SBJSON *parser = [[SBJSON alloc] init];
NSString *responseString = [request responseString];
NSString *json_string = [[NSString alloc] initWithData:responseString encoding:NSUTF8StringEncoding];
NSArray *statuses = [parser objectWithString:json_string error:nil];
But I get EXC_BAD_ACCESS at this line
NSString *json_string = [[NSString alloc] initWithData:responseString encoding:NSUTF8StringEncoding];
saying variable json_string is not a CFString.
Can someone help me solve this and tell me how to act further to acces the JSON components?Thank you:)
EDIT:
{
items = (
{
name = "Poza 1";
target = "http://myaudi.fr";
url = "http://test.res-novae.fr/sfrplay/upload/image/pic1_iphone3.jpg";
"url_thumb" = "http://test.res-novae.fr/sfrplay/upload/thumb/pic1_iphone3_thumb.jpg";
},
{
name = "Poza 2";
target = "http://audifrance.fr";
url = "http://test.res-novae.fr/sfrplay/upload/image/pic2_iphone3.jpg";
"url_thumb" = "http://test.res-novae.fr/sfrplay/upload/thumb/pic2_iphone3_thumb.jpg";
}
);
name = "Playlist 1";
},
{
items = (
{
name = "Poza 3";
target = "http://google.ro";
url = "<null>";
"url_thumb" = "<null>";
}
);
name = "Playlist 2";
}
You should use one of the JSON frameworks available out there, i.e. JSONKit or json-framework, which both makes it really easy to convert strings to JSON objects (i.e. an NSDictionary).
If you're using json-framework, you'd only have to do the following (if you've included JSON.h):
NSDictionary *jsonObject = [responseString JSONValue];
There is a issue with your line
NSString *json_string = [[NSString alloc] initWithData:responseString encoding:NSUTF8StringEncoding];
you have declared responseString as NSString *responseString = [request responseString];
and you are giving it as Data while allocating json_string
You do not need this line
NSString *json_string = [[NSString alloc] initWithData:responseString encoding:NSUTF8StringEncoding];
responseString is already a string (and initWithData: expects a NSData object not NSString). Just feed it straight to the parser:
NSArray *statuses = [parser objectWithString:responseString error:nil];
Can someone help me solve this and tell me how to act further to acces
the JSON components?
You now have a nice NSArray of NSDictionary objects representing your JSON data, you can access the first item, represented by
{"name":"Playlist 1","items":[{"name":"Poza 1","target":"http:\/\/myaudi.fr","url":"http:\/\/test.res-novae.fr\/sfrplay\/upload\/image\/pic1_iphone3.jpg","url_thumb":"http:\/\/test.res-novae.fr\/sfrplay\/upload\/thumb\/pic1_iphone3_thumb.jpg"},{"name":"Poza 2","target":"http:\/\/audifrance.fr","url":"http:\/\/test.res-novae.fr\/sfrplay\/upload\/image\/pic2_iphone3.jpg","url_thumb":"http:\/\/test.res-novae.fr\/sfrplay\/upload\/thumb\/pic2_iphone3_thumb.jpg"}]}
by getting the first element in the array
NSDictionary* dict = [statuses objectAtIndex:0];
and the keys in the dictionary should be "name", and "items". The object for "name" will be an NSString and the object for "items" will be an NSArray containing further NSDictionary objects describing each item.
I read a plist data at LightTableViewController.m
and I load a data like this :
LOG RESULT:
The Plist Data Is : (
{
category = 11;
id = 1;
name = "LIVING RM";
status = 0;
},
{
category = 11;
id = 2;
name = "BEDROOM RM";
status = 0;
}
)
I need to post the "id" and "status" back to the database
to control which light to turn on or turn off
And this part is the my post method,It's in LightCell0.m
- (void)switchToggled:(id)sender {
UISwitch *theSwitch = (UISwitch *)sender;
UITableViewCell *cell = (UITableViewCell *)theSwitch.superview.superview;
UITableView *tableView = (UITableView *)cell.superview;
NSIndexPath *indexPath = [tableView indexPathForCell:cell];
if(theSwitch.on) {
NSURL * url;
NSMutableURLRequest * request;
NSString *_urlString = #"http://10.85.28.99/req_light.php";
url = [self smartURLForString:_urlString];
request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
//This is my first post method,it is static,only get the indexPath,Not a real id and status I want to post back
NSString *post = [NSString stringWithFormat:#"lightcb%i=1", indexPath.row+1];
NSData *postData = [ NSData dataWithBytes: [ post UTF8String ] length: [ post length ] ];
[request setHTTPBody:postData];
self.connection = [NSURLConnection connectionWithRequest:request delegate:self];
}
else {
NSURL * url;
NSMutableURLRequest * request;
NSString *_urlString = #"http://10.85.28.99/req_light.php";
url = [self smartURLForString:_urlString];
request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
//I got one error and one warring
//Error is "Request for member 'plist' in something not a structure or union"
//Warning is 'NSString' may not resopnd to '+stringWithFormat:value=ForKey'
NSString *post = [ NSString stringWithFormat:#"id=%i,status=0",
[[self.plist objectAtIndex:indexPath.row] valueForKey:#"id"]];
NSData *postData = [ NSData dataWithBytes: [ post UTF8String ] length: [ post length ] ];
[request setHTTPBody:postData];
self.connection = [NSURLConnection connectionWithRequest:request delegate:self];
}
}
So...my question is
<1>How to post two data back (is it right to use "," to separated two return variables ?
<2>How to eliminate the error "Request for member 'plist' in something not a structure or union"
Great Thanks
1) POST values are separated by '&' like GET values in an URL.
2) The 'Request for member'... line tells you that your member does not exist, or at least is not declared in this scope, the warning 'NSString may not respond...' tells you you're trying to invoke a message/method on NSString which should be invoked on another class (NSDictionary would be my guess here).