Determining Issue With Retrieving JSON from URL in iPhone - ios

Let me start off by saying that I am not particularly trying to find a solution, just the root cause of the problem. I am trying to retrieve a JSON from a url. In browser, the url call works just fine and I am able to see the entire JSON without issue. However, in x-code when simply using NSURLConnection, I am getting data bytes, but my NSString is null.
theString = [[NSString alloc] initWithData:urlData encoding:NSUTF8StringEncoding];
After doing some research I have found that I am probably trying to use the wrong encoding. I am not sure what type of encoding is being used by the url, so on first instinct I just tried some random encoding types.
NSString* myString = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSString* myString2 = [[NSString alloc] initWithData:data encoding:NSUTF16StringEncoding];
NSString* myString3 = [[NSString alloc] initWithData:data encoding:NSWindowsCP1252StringEncoding];
NSASCIIStringEncoding and NSWindowsCP1252StringEncoding is able to bring back a partially correct JSON. It is not the entire JSON thatI am able to view in the browser, and some characters are a little messed up, but it is something. To try and better determine what encoding was used, I decided to use the following method to try and determine it by looking at what encoding returned.
NSError *error = nil;
NSStringEncoding encoding;
NSString *my_string = [[NSString alloc] initWithContentsOfURL:url
usedEncoding:&encoding
error:&error];
My NSStringEncoding value is 3221214344. And this number is consistent everytime I run the app. I can not find any NSStringEncoding values that even come close to matching this.
My final question is: Is the encoding used for this url not consumable by iOS, is it possible that multiple types of encoding was used for this url, or is there something else that I could be doing wrong on my end?

It's best not to rely on Cocoa to figure out the string encoding if possible, especially if the data might be corrupted. A better approach would be to check if the value indicated by the HTTP Content-Type header specifies a character set like in this example:
Content-Type: text/html; charset=ISO-8859-4
Once you're able to parse and retrieve a character set name from the Content-Type header, you need to convert it to an NSStringEncoding, first by passing it to CFStringConvertIANACharSetNameToEncoding, and then passing the returned CF string encoding to CFStringConvertEncodingToNSStringEncoding. After that, you can initialize your string using -[NSString initWithData:encoding:].
NSData *HTTPResponseBody = …; // Get the HTTP response body
NSString *charSetName = …; // Get a charset name from the Content-Type HTTP header
// Get the Core Foundation string encoding
CFStringEncoding cfencoding = CFStringConvertIANACharSetNameToEncoding((CFStringRef)charSetName);
// Confirm this is a known encoding
if (cfencoding != kCFStringEncodingInvalidId) {
// Initialize the string
NSStringEncoding nsencoding = CFStringConvertEncodingToNSStringEncoding(cfencoding);
NSString *JSON = [[NSString alloc] initWithData: HTTPResponseBody
encoding: nsencoding];
}
You still may run into problems if the string data you're working with is corrupted. For example, in the above code snippet, perhaps charSetName is UTF-8, but HTTPResponseBody can't be parsed as UTF-8 because there's an invalid byte sequence. In this situation, Cocoa will return nil when you try to instantiate your string, and short of sanitizing the data so that it conforms to the reported string encoding (perhaps by stripping out invalid byte sequences), you may want to report an error back to the end user.
As a last-ditch effort — rather than reporting an error — you could initialize a string using an encoding that can handle anything you throw at it, such as NSMacOSRomanStringEncoding. The one caveat here is that unicode / corrupted data may show up intermittently as symbols or unexpected alphanumerics.

Even though it seems that the answer has been provided in the comments (using iso-8859-1 as the correct encoding) I thought it worthwhile to discuss how I would go about debugging this problem.
You said that the Desktop Browser (Chrome) can digest the data correctly, so let's use that:
Enable Developer Tools https://developers.google.com/chrome-developer-tools/
When the Dev Tools window is open, switch to "network" and execute your call in that browser tab
check the output by clicking on the request url - it should give you some clue.
If that doesn't work, tools like Postman can help you to recreate the call before you implement it on the device

Related

Can't decode NSString well

I had my server encoding in ISO-8859-1 and decided to chango into UTF-8. The problem is that the filenames creates in ISO now crashes because I change the encoding type in my code. I try to connect with an iOS app and show the directories and files, the news are shown well but the olds with ISO not.
How can I detect if the filename is in one or other encoding to process in the right way each one? Because now, the filename in ISO it can be represent in UTF-8 but the string to access is not the same. (Ex: %E1p%F1 --> %C3%A1p%C3%B1)
I try this, but it doesn't work:
NSString *isoL = [item.href stringByAddingPercentEscapesUsingEncoding:NSISOLatin1StringEncoding];
char const *iso2utf = [isoL UTF8String];
NSString *utf = [[NSString alloc]initWithCString:iso2utf encoding:NSUTF8StringEncoding];
You need to have the server declare the content encoding of the response, much like how HTTP does.
I don't believe it's possible to auto-detect ISO-8859-1/UTF-8 text encoding.

NSJSONSerialization encoding?

I'm trying to convert my NSDictionary to a json string and then send the data to my web api via HTTPBody (POST request). I convert my dictionary to json like this:
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionary options:0 error:&error];
What I found is that this above method, is not encoding my data (at least special characters like ampersand is not being handled). So the data received on the server side is a mess and I can't read it properly.
For more details on what is happening, assume the following dictionary:
"salutation":"Mrs."
"companyName":"T & F LLP"
"firstName":"Tania"
"country":"Canada"
This dictionary is converted to NSData using the above method and later used like this
[request setHTTPBody:nsDataFromJson];
What do I receive on the server side? I get this
{"contact":"{\"firstName\":\"Tania\",\"salutation\":\"Mrs.\",\"company\":\"Aird
I only get the data up to the special character & and I can only assume that this is happening because the first method I mentioned is not encoding special characters like the &
So I solved this (just for the time being) by converting the dictionary into a json string then replacing each & with %26 then creating NSData from this new string (with the special characters handled). Then I get the full body on my server.
So any idea how to properly handle this?
By the way, the same problem occurs if I use SBJSON too.
It has been 3 months, so I guess the problem must have been solved by now.
The reason the received JSON data is corrupted is because the parser interpreted & (ampersand) as a part of the URL address. Borrowing some codes from this link, I wrote this function to percent-encode & and a few other characters that may get confused:
+ (NSDictionary*) percentEncodeDictionayValues:(NSDictionary*) dict
{
NSMutableDictionary* edict=[NSMutableDictionary dictionaryWithDictionary:dict];
NSMutableCharacterSet* URLQueryPartAllowedCharacterSet = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy];
[URLQueryPartAllowedCharacterSet removeCharactersInString:#"?&=#+/'"];
for(NSString* key in [dict allKeys])
{
if([dict[key] isKindOfClass:[NSString class]])
edict[key] = [dict[key] stringByAddingPercentEncodingWithAllowedCharacters:URLQueryPartAllowedCharacterSet];
}
return edict;
}
So you can preprocess your NSDictionary object with this function before feeding into NSJSONSerialization, and the received data will have & and other characters preserved.

Issue in GDataXMLDocument when try [dataUsingEncoding:NSUTF8StringEncoding]?

I am using GDataXMLDocument. I need to parse very simple XML string. When I try to init XML with string I receive error:
-[myObj dataUsingEncoding:]: unrecognized selector sent to instance 0x7afb5690
My string is:
<rootNode>
<detail1>value</detail1>
<detail2>value</detail2>
<detail3>value</detail3>
<detail4>value</detail4>
</rootNode>
The line of the error is:
NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
where I need to encode my string no NSData, so I can init my parser with it.
I suppose the problem is in NSUTF8StringEncoding, but I can not understand why!
I am using ARC with NON ARC for GDataXML set in compilation options.
How to solve this?
P.S. I have a remark which might be important. I receive an array from SOAP service. I used sudzc.com tool to create my classes. The SOAP service send to me array of structures. When I receive data using po command see what is inside and I decided that it consists of NSArray with XML sting inside. In general I extract each element of an array and try to parse it as XML to extract data I need.
May be I am wrong and that is the reason for that error.
I don't know why but I fix it casting once again to NSString with format using:
NSString *properStr = [NSString stringWithFormat:#"%#", str];
I am not sure why I need this, but it is wotking now.

NSData to NSString not working (for use in QCComposition)

I have A NSdata value that it needs to be converted into a string.
So far my app works fine loading a QC composition from a server however, I have a warning when I tell QC to load data from server.
It loads the file just fine but is there a way to avoid this worming?
I have tried to convert data to string using
NSString* newStr = [[NSString alloc] initWithData:urlData
encoding:NSUTF8StringEncoding];
HOwever, it is giving a null location of the file
Find the way I was loading the file with wrong method the correct one is:
QCComposition *qc = [QCComposition compositionWithData:urlData];

ios issue with stringByAddingPercentEscapesUsingEncoding

In my app I need to send some parameters to the url, when I am trying with the stringByAddingPercentEscapesUsingEncoding it is not converting correctly. If I am not using this encoding I am getting null(Exception) from the nsurl.Here is me code.
http://www.mycompurl.co?message=xyz&id=____ here I am sending the id 1 or 2 or any number.
when I convert this string to url by using stringByAddingPercentEscapesUsingEncoding I got
"http://www.mycompurl.co?message=xyz&id=**%E2%80%8B**1" (when I send 1 as parameter). Then I got the 0 data from the Url.
str = [NSString stringWithFormat:#"%#?message=xyz&id=​%#",Application_URL,bootupdateNew];
str = [str stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
url=[NSURL URLWithString:str];
NSError* error = nil;
data1 = [NSData dataWithContentsOfURL:url options:NSDataReadingUncached error:&error];
Thank you In advance
Basics
A URL is composed of several components.
Each component has its own rule how the component's source string must be encoded, so that this component becomes valid within the URL string.
Applying stringByAddingPercentEscapesUsingEncoding: will never always produce a correct URL if the string consists of more than one component (and if we assume, we have an unbounded set of source strings - so that the encoded string actually differs from the source string).
It even won't work always with a string which represents any single component.
In other words, for what's worth, stringByAddingPercentEscapesUsingEncoding: should not be used to try to make a URL out of several components. Even getting the URL query component correctly encoded is at least error prone, and when utilizing stringByAddingPercentEscapesUsingEncoding: it still remains wonky. (You may find correct implementations on SO, though - and I posted one myself).
But now, just forget about it:
It took awhile for Apple to recognize this failure, and invented NSURLComponents. It's available since iOS 7. Take a look! ;)

Resources