My application is not parsing the JSON response - objective-c

when i try to parse the JSON response, i got an empty response and this error:
JSONValue failed. Error trace is: (
"Error Domain=org.brautaset.JSON.ErrorDomain Code=11 \"Unexpected end of string\" UserInfo=0x797c420 {NSLocalizedDescription=Unexpected end of string}"
)
This is how i try to send the JSON request and how i tried to parse its response:
send the JSON request:
- (void)viewWillAppear:(BOOL)animated{
//Specify the adress of the webservice (url)
NSURL *url = [NSURL URLWithString:#"http://xxxxxxxxxxx.com/webservices/"];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
NSString *jsonStringArray=[aMutableArray JSONRepresentation];
NSLog(#"-------------");
NSLog(#"%#",jsonStringArray);
NSLog(#"-------------");
[request setPostValue:jsonStringArray forKey:#"liste_des_themes"];
NSLog(#"The response string is: %#",request.responseString);
[request setDelegate:self];
[request startAsynchronous];
}
For the NSLog where i tried to display the json string before sending it i got a correct JSON format:
NSLog(#"%#",jsonStringArray);//["Mairie","Préfectures et sous-préfectures"]
Now for the second NSLog, i got null:
NSLog(#"The response string is: %#",request.responseString);//The response string is: (null)
When parsing the response:
-(void)requestFinished:(ASIHTTPRequest *)request
{
if(request.responseStatusCode==200)
{
NSLog(#"This block gets called, response code is 200");//This block gets called, response code is 200
//parse the response
NSLog(#"The response string is: %#",request.responseString);
NSString *responseString=[request responseString];
NSDictionary *responseDict=[responseString JSONValue];
}
}
For the NSLog trying to display the response string, i got nothing, neither null, nor a correct value:
NSLog(#"The response string is: %#",request.responseString);
//The response string is:
And after that, i got this trace error:
JSONValue failed. Error trace is: (
"Error Domain=org.brautaset.JSON.ErrorDomain Code=11 \"Unexpected end of string\" UserInfo=0x797c420 {NSLocalizedDescription=Unexpected end of string}"
)
Can you help me there? thanx in advance.

I would assume you have no control over the web service, so telling you to do something about that is generally a non-starter.
1) First, make sure that the JSON response looks correct. Can you download it into a browser and see that it looks okay?
2) If it looks okay, can it pass a JSON lint test? (Try jsonlint.com, and plug it in there.)
3) If it passes (1) and (2), then see if it has any leading nulls in the returned data response. I found this to be the case in my own code. I could not work directly with this without first removing the leading nulls.
Unfortunately, I'm not at my mac to copy the code I use to solved this problem. But it was a real problem, and the solution is to remove the nulls (There were thousands of them in my case.) Nulls in a sting look like the string terminator, so leading nulls hide the real content.

You have a problem with the web service that serves up the JSON. Debug that and you will find the problem.

Related

Objective-C UNIRest has no response to GET Request

I am attempting the use the UNIRest API to run this get request in an iPhone application
https://api.guildwars2.com/v1/guild_details.json?guild_name=The%20Legacy
The code I am running is this
NSDictionary* headers = #{#"accept": #"application/json"};
NSDictionary* parameters = #{#"guild_name": #"The Legacy"};
UNIHTTPJsonResponse* response = [[UNIRest post:^(UNISimpleRequest* request) {
[request setUrl:#"https://api.guildwars2.com/v1/guild_details.json"];
[request setHeaders:headers];
[request setParameters:parameters];
}] asJson];
NSDictionary *guildInformation = response.body.JSONObject;
NSLog(#"response length: %lu", (unsigned long)[guildInformation.allValues count]);
for(NSString *key in [guildInformation allKeys]) {
NSLog(#"key: %# object: %#", key, [guildInformation objectForKey:key]);
}
I had hoped the for loop would display the response. But it seems I get no response at all when you see that the only output is,
response length: 0
I don't know the UNIRest API well enough to fix this and cannot find any good documentation for it. What am I doing wrong?
The problem seems to be that the parameters values are not correctly encoded.
As a fast workaround you can simply pass the entire constructed URL.
UNIHTTPJsonResponse* response = [[UNIRest post:^(UNISimpleRequest* request) {
[request setUrl:#"https://api.guildwars2.com/v1/guild_details.json?guild_name=The%20Legacy"];
[request setHeaders:#{#"accept": #"application/json"}];
}] asJson];
Probably the space in #"The Legacy" doesn't translate to "The%20Legacy", will do a test case before adding issue to https://github.com/Mashape/unirest-obj-c
UPDATE
Only while I was adding a TestCase for spaced values (which do work correctly) I spotted that you where using POST while you should have used GET.
UNIHTTPJsonResponse* response = [[UNIRest get:^(UNISimpleRequest* request) {

retrieving certain keys from a returned JSON in Objective C

I am sending a JSON encoded POST type to a server of mine which reads the sent information in PHP and decodes it there. Now when I re-encode it and send it back it works perfectly and I can NSLog the response but my issue is how do I get a specific section of the response?
Here is an example response:
responseString: {"status":"ok","code":0,"original request":{"username":"test"
`,"password":"test"}}`
Suggestions, thoughts?
What you are receiving is actually a 'dictionary of objects'. You can separate the data in the above code as follows:
First, serialize the response data using JSON serialization as follows:
NSError* error;
NSDictionary* responseDictionary = [NSJSONSerialization JSONObjectWithData:returnData options:nil error:&error];
You may then separate the dictionary as you wish.For instance, if you want to retrieve the value for "status", you may use:
NSString *status = [responseDictionary objectForKey:#"status"];
Or, if you want to retrieve "original request" which is another dictionary, you may use:
NSDictionary *originalRequest = [responseDictionary objectForKey:#"original request"];
Hope this helps!
The response received from the server is JSON data.
Here is an excellent tutorial on JSON parsing for iOS and there are plenty of tutorials & docs if you browse.
http://www.raywenderlich.com/5492/working-with-json-in-ios-5
In JSON, "{}" represents a dictionary and "[]" is an array. So, try this
NSDictionary* originalRequest = [responseString objectForKey:#"original request"];
you can dig in further like this,
NSString* username = [originalRequest objectForKey:#"username"];
I strongly recommend you to read some tutorials on JSON.

RestKit PUT not working

I'm trying to do a fairly basic HTTP PUT using RestKit. I don't want to put the entire object, since the API call was designed to accept a single query parameter and just update that field. I've tried two approaches so far, both unsuccessful.
URL to post to: https://myserver/api/users/{userId}
Query string parameter: verificationCode=
Example usage: PUT https://myserver/api/users/101?verificationCode=646133
Approach #1: Put the query parameter in a RKParams object and make the PUT call with those params.
NSString *putUrl = [NSString stringWithFormat:#"/api/users/%i", [APIUserInfo sharedAPIUserInfo].apiUserIdx];
NSLog(#"the PUT url is %#", putUrl);
// Send a PUT to a remote resource. The dictionary will be transparently
// converted into a URL encoded representation and sent along as the request body
NSDictionary* paramsDict = [NSDictionary dictionaryWithObject:[_verificationCode text] forKey:#"verificationCode"];
// Convert the NS Dictionary into Params
RKParams *params = [RKParams paramsWithDictionary:paramsDict];
[[RKClient sharedClient] put:putUrl params:params delegate:self];
Approach #2: Build the entire url and try a PUT with params set to nil.
NSString *putUrl = [NSString stringWithFormat:#"/api/users/%i?verificationCode=%#", [APIUserInfo sharedAPIUserInfo].apiUserIdx, [_verificationCode text]];
NSLog(#"the PUT url is %#", putUrl);
[[RKClient sharedClient] put:putUrl params:nil delegate:self];
Neither approach is working for me. The first fails saying "RestKit was asked to retransmit a new body stream for a request. Possible connection error or authentication challenge?" then runs for about 10 seconds and times out. The second approach fails saying HTTP Status 405 - Method Not Allowed.
Can anyone point out where I'm going wrong, or provide me with a simple PUT example using RestKit? Most of the examples I've found at there are putting the entire object which I don't want to do in this case.
UPDATE:
Approach #2 worked well once I got a few things sorted out on the server side. Final solution:
NSString *putUrl = [NSString stringWithFormat:#"/api/users/verify/%i?verificationCode=%#", [APIUserInfo sharedAPIUserInfo].apiUserIdx, [_verificationCode text]];
NSLog(#"the PUT url is %#", putUrl);
[[RKClient sharedClient] put:putUrl params:nil delegate:self];
the HTTP PUT method is disabled on your webserver. It is by default on all webserver for security reasons.
HTTP Status 405 - Method Not Allowed.

Getting info from NSData object

How would I get returningResponse (into say, a NSString) from the following code:
NSURLResponse* response;
NSError* error;
NSData* result = [NSURLConnection sendSynchronousRequest:theRequest returningResponse:&response error:&error];
I think I can get the info that I need into a string but I can't call anything on response because it's null. Therefore, I assume that I need to call something on result. The problem is, I don't know what to call.
(The URL request has been coded prior to the code sample. I know that that works.) I want to be able to detect if the request as successful.
According to the documentation for the URL loading system:
If NSURLConnection is unable to download the URL the method will return nil and any available NSError instance by-reference in the appropriate parameter.
So, see what's in your "error" parameter to find out what the problem is.

Generate JSON object with transactionReceipt

I've been the past days trying to test my first in-app purchse iphone application. Unfortunately I can't find the way to talk to iTunes server to verify the transactionReceipt.
Because it's my first try with this technology I chose to verify the receipt directly from the iPhone instead using server support. But after trying to send the POST request with a JSON onbject created using the JSON api from google code, itunes always returns a strange response (instead the "status = 0" string I wait for).
Here's the code that I use to verify the receipt:
- (void)recordTransaction:(SKPaymentTransaction *)transaction {
NSString *receiptStr = [[NSString alloc] initWithData:transaction.transactionReceipt encoding:NSUTF8StringEncoding];
NSDictionary *jsonDictionary = [NSDictionary dictionaryWithObjectsAndKeys:#"algo mas",#"receipt-data",nil];
NSString *jsonString = [jsonDictionary JSONRepresentation];
NSLog(#"string to send: %#",jsonString);
NSLog(#"JSON Created");
urlData = [[NSMutableData data] retain];
//NSURL *sandboxStoreURL = [[NSURL alloc] initWithString:#"https://sandbox.itunes.apple.com/verifyReceipt"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"https://sandbox.itunes.apple.com/verifyReceipt"]];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:[jsonString dataUsingEncoding:NSUTF8StringEncoding]];
NSLog(#"will create connection");
[[NSURLConnection alloc] initWithRequest:request delegate:self];
}
maybe I'm forgetting something in the request's headers but I think that the problem is in the method I use to create the JSON object.
HEre's how the JSON object looks like before I add it to the HTTPBody :
string to send: {"receipt-data":"{\n\t\"signature\" = \"AUYMbhY
...........
D0gIjEuMCI7Cn0=\";\n\t\"pod\" = \"100\";\n\t\"signing-status\" = \"0\";\n}"}
The responses I've got:
complete response {
exception = "java.lang.IllegalArgumentException: Property list parsing failed while attempting to read unquoted string. No allowable characters were found. At line number: 1, column: 0.";
status = 21002;
}
Thanks a lot for your guidance.
I have just fixed that after 2 days of struggling. You have to encode receipt using Base64 before inserting into json object. Like that (Ruby):
dataForVerification = {"receipt-data" => Base64.encode64(receipt)}.to_json
Base64 is not mentioned anywhere in the official docs (at least for SDK 3.0), only on a couple of blogs.
For instance, here the guy encodes the receipt in Base64 before passing it to the PHP server, but does not decode it back in PHP, thus sending Base64-encoded string to iTunes.
Re: "21002: java.lang.IllegalArgumentException: propertyListFromString parsed an object, but there's still more text in the string.:"
I fixed a similar issue in my code by wrapping the receipt data in {} before encoding.
The resulting receipt looks like:
{
"signature" = "A[...]OSzQ==";
"purchase-info" = "ew[...]fQ==";
"pod" = "100";
"signing-status" = "0";
}
Here's the code I use:
receipt = "{%s}" % receipt // This step was not specified - trial and error
encoded = base64.b64encode(receipt)
fullpost = '{ "receipt-data" : "%s" }' % encoded
req = urllib2.Request(url, fullpost)
response = urllib2.urlopen(req)
Apple's Response:
{"receipt":{"item_id":"371235", "original_transaction_id":"1012307", "bvrs":"1.0", "product_id":"com.foo.cup", "purchase_date":"2010-05-25 21:05:36 Etc/GMT", "quantity":"1", "bid":"com.foo.messenger", "original_purchase_date":"2010-05-25 21:05:36 Etc/GMT", "transaction_id":"11237"}, "status":0}
Good luck!