I am making a call to get a JSON response like this:
NSData *urlData=[NSURLConnection sendSynchronousRequest:serviceRequest returningResponse:&httpResponse error:nil ];
NSString *returnString=[[NSString alloc]initWithData:urlData encoding:NSUTF8StringEncoding];
However, when I print the string using NSLog:
Emiratos �rabes Unidos
When I convert it to NSData like this:
NSData *jsonData = [returnString dataUsingEncoding:NSUTF8StringEncoding];
NSArray * response = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil];
It turns it to be (when I retrieve the value from the array):
Emiratos \Ufffdrabes Unidos
And when I put it in a label it displays it like this:
Emiratos �rabes Unidos
I would like to display in a label like this:
Emiratos Árabes Unidos
How can I do it?
The problem seems to be this line:
NSString *returnString =
[[NSString alloc] initWithData:urlData
encoding:NSUTF8StringEncoding];
You are assuming that the data is a string encoded as UTF8. But apparently it isn't. Therefore you're seeing the "replacement character" (codepoint U+FFFD) at this point.
You'll need to find out what encoding is actually being used. You can probably just experiment with other encodings. Alternatively, use NSLog to look at the data; an NSData object is logged as a sequence of hex bytes, so by looking at the bytes in that position, and by looking up various encodings on the Internet, you may be able to deduce what encoding is being used here.
(But if you use NSLog and you actually see FFFD at this point, then you've had it; the server itself is supplying the bad data and there's nothing you can do about it, as the good data is lost before you can get at it.)
Related
I am converting NSData to NSString which I got as response of a url using the following method.
NSString *result = [[NSString alloc] initWithData:_Data encoding:NSUTF8StringEncoding];
It works fine and I am using this for a long time but today I faced an issue while loading the data (paging) at one page my result gives null string.
So I searched SO and found a method from this link NSData to NSString converstion problem!
[NSString stringWithCString:[theData bytes] length:[theData length]];
and this works fine.
My queries,
The method was deprecated in iOS 2.0. If I use this will I be facing any issue in future?
I think this is the text that made the method fail What is this and is there any way that I can encode this using NSUTF8StringEncoding?
What is the the alternative encoding that I can use for encoding all the type of characters like in the above pic?
In order to obtain the type of the content which is sent by the server, you need to inspect the Content-Type header of the response.
The content type's value specifies a "MIMI type", e.g.:
Content-Type: text/plain
A Content-Type's value may additionally specify a character encoding, e.g.:
Content-Type: text/plain; charset=utf-8
Each MIME type should define a "default" charset, which is to be used when there is no charset parameter specified.
For text/* media types the default charset is US-ASCII.
(see RFC 6657, §3).
The following code snippet demonstrates how to safely encode the body of a response:
- (NSString*) bodyString {
CFStringEncoding cfEncoding = NSASCIIStringEncoding;
NSString* textEncodingName = self.response.textEncodingName;
if (textEncodingName) {
cfEncoding = CFStringConvertIANACharSetNameToEncoding( (__bridge CFStringRef)(textEncodingName) );
}
if (cfEncoding != kCFStringEncodingInvalidId) {
NSStringEncoding encoding = CFStringConvertEncodingToNSStringEncoding(cfEncoding);
return [[NSString alloc] initWithData:self.body encoding:encoding];
}
else {
return [self.body description];
}
}
Note:
body is a property returning a NSData object representing the response data.
response is a property returning the NSHTTPURLResponse object.
If
NSString *result = [[NSString alloc] initWithData:_Data encoding:NSUTF8StringEncoding];
returns nil then _Data does not contain a valid string in UTF-8 encoding.
You said that
[NSString stringWithCString:[theData bytes] length:[theData length]];
works fine in your case. This method
interprets the data bytes in the "default C string encoding", but it is unspecified which
encoding that is (and therefore this method is deprecated and should not be used).
I think the default C string encoding is still "Mac Roman". In that case
NSString *result = [[NSString alloc] initWithData:_Data encoding:NSMacOSRomanStringEncoding];
would be the correct solution. But in any case, you should find out which encoding
the web service uses for the response, and specify that in the initWithData:encoding:
method.
Try this
NSString *theString = [NSString stringWithFormat:#"To be continued%C", ellipsis];
NSData *asciiData = [theString dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *asciiString = [[NSString alloc] initWithData:asciiData encoding:NSASCIIStringEncoding];
NSLog(#"Original: %# (length %d)", theString, [theString length]);
NSLog(#"Converted: %# (length %d)", asciiString, [asciiString length]);
It is due to the uncorrect string encoding.
You can try:
save the NSData to the disk with dataPath
use the NSString class method to create the string:
+ (id)stringWithContentsOfURL:(NSURL *)url usedEncoding:(NSStringEncoding *)enc error:(NSError **)error
Notice here:
enc
Upon return, if url is read successfully, contains the encoding used to interpret the data.
So if the method successes, you can get the correct string and all is done by the iOS.
I need some kind of json string generator for objective-c. Actually I thought there must be something like that but I could not find anything.To be specific, for example I have a json string like:
{"name":"abc","email":"def#ghi.com","password":"1"}
when I want to store it in objective c, I have to write it like:
#"{\"name\":""\"abc\""",\"email\":""\"def#ghi.com\""",\"password\":""\"1\"""}"
so it is confusing and hard to implement. Are there any generators or an easy way to implement it. Thanks
Convert your json string to dictionary...
NSData* data = [yourJsonString dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary* jsonDict = [NSJSONSerialization
JSONObjectWithData:data
options:kNilOptions
error:&error];
NSLog(#"jsonDict:%#",jsonDict);
You can use the native ios SDK API's for generating JSON data from NSDictionary / NSArray.
e.g.,
NSData *jsondata = [NSJSONSerialization dataWithJSONObject:(dictobject) options:NSJSONWritingPrettyPrinted error:&error];
NSString *str = [[NSString alloc] initWithData:jsondata encoding:NSUTF8StringEncoding];
may this helps!
Use it
Also Import"JSON.H"
NSDictionary *googleResponse = [[NSString stringWithContentsOfURL:[NSURL URLWithString:website] encoding: NSUTF8StringEncoding error: NULL] JSONValue];
be careful...in your original question, when referring to how to store it in objective-c, i think you made a mistake
you wrote :
#"{\"name\":""\"abc\"""
when it shoud be
#"{\"name\":\"abc\",....etc...
i think you doubled the quotes...be wary, cause in the beginning there already is one opening double-quote #", all the other needed quotes must be escaped like so \", and then also have an ending quote as well.
hope it helps
I have an app that just opened call a webserver page that gives me a json string.
When I'm on the local network all works without problem but when I open the app outside the local network and without vpn the app crashes.
How can I control the json string?
This is my code:
NSString *urlstr = [[NSString alloc] initWithFormat:#"%#yes.php", av];
NSURL *url = [[NSURL alloc] initWithString:urlstr];
NSError* error = nil;
NSString* urlString = [NSString stringWithContentsOfURL:url encoding:NSASCIIStringEncoding error:&error];
NSString *newStr;
NSData* data=[newStr dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:data
options:kNilOptions
error:&error];
sn1 = [[json objectForKey:#"Rele1"] intValue];
I want to compare the json answer with a NULL value, if the two parameters are equal I show an alert.
EDIT: If I try to read any value, the app crashes waiting the json reply...
I have bypassed the problem with an NSURLRequest with the timeoutInterval parameter that closes the connection after n seconds.
Amongst other things, you fail to:
check whether the attempt to fetch an ASCII-encoded string from a remote URL failed (obvious possibilities: the URL is unreachable, the result is UTF-8 rather than ASCII);
check whether the JSON parsing succeeds (obvious possibility: the server 404d and returned an HTML error page instead)
check whether the returned JSON object was actually a dictionary (eg, it could be an array, in which case calling objectForKey: on it will raise an exception)
The parsing of return data as ASCII then re-encoding into UTF-8 is also probably redundant — because the one supersets the other it has the effect of a threshold test, otherwise preventing acceptable results from proceeding.
Does this code ever worked?
You should check error after [NSString stringWithContentsOfURL:url encoding:NSASCIIStringEncoding error:&error];
you are reading URL data into urlString but then get NSData from uninitialized newStr and parse it?
again you should always check error whenever you provide it before anything else
why do you read the data as ASCII but the NSData as UTF8?
I access a RESTFUL url and get back results. The results are in JSON. I turn the response into a string via:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSString *json = [[NSString alloc] initWithBytes:[self.receivedData mutableBytes] length:[self.receivedData length] encoding:NSUTF8StringEncoding];
The json variable has a value of 0x0. When I mouse over it, I see <Invalid CFStringRef>. How can I debug this to tell why it is invalid? I render the JSON given back through the browser in A JSON parser. That checks out fine.
Results are given back by entering an ID in the URL. Other IDs return results without issue. The result set is fairly large.
First I would use initWithData:encoding: to setup the NSString. Small difference, but that method is there for a reason.
Then, I would do a hexdump of self.receivedData to see what is actually in there. If that data is not properly UTF8 encoded then the initWithData:encoding: will fail.
(Google for NSData hex dump to find other people's utility functions to do this)
I have found that sometimes web services are sloppy with their encoding. So I usually implement a fallback like this:
NSString* html = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
if (html == nil) {
html = [[NSString alloc] initWithData: data encoding: NSISOLatin1StringEncoding];
if (html == nil) {
html = [[NSString alloc] initWithData: data encoding: NSMacOSRomanStringEncoding];
}
}
It is kind of sad that this is required but many web services are not written or configured properly.
Use NSLog to look at the bytes.
So I have the following code:
NSURL *baseURL = [NSURL URLWithString:#"http://www.baseurltoanxmlpage.com"];
NSURL *url = [NSURL URLWithString: #"page.php" relativeToURL:baseURL];
NSArray *array = [NSArray arrayWithContentsOfURL:url];
If the XML page is as follows:
<array><dict><key>City</key><string>Montreal</string></dict></array>
The array returns fine. However, if the XML file is as follows:
<array><dict><key>City</key><string>Montréal</string></dict></array>
The array returns null. I guess this has something to do with the special char "é".
How would I deal with these characters? The XML page is generated with PHP. utf8_encode() function makes the array return but then I don't know how to deal with the encoded "é" character.
Here's the working solution:
NSString *stringArray = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
NSArray *array = [stringArray propertyList];
NSLog(stringArray);
NSLog(#"%#", array);
NSLog([[[array objectAtIndex:0] valueForKey:#"City"] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]);
The first log prints out the "é" fine.
In the second log, it's encoded and is printed as "\U00e9".
In the 3rd log, it's decoded and printed as "é" (which is what I was looking for).
As you noted, you need to return a UTF8- or UTF16-encoded XML document. Then make NSString objects using the stringByReplacingPercentEscapesUsingEncoding: method, using the relevant encoding.
NSString has a method to return data in encoding, data read from the URL:
+(id)stringWithContentsOfURL:encoding:error:
Look under String Encodings section for possible encodings to find the one suitable.
Looking at the NSString documentation for :propertyList, we see:
Parses the receiver as a text representation of a property list, returning an NSString, NSData, NSArray, or NSDictionary object, according to the topmost element.
A property list is an Apple-specific document that stores representations of NSString, NSDictionary, NSArray, and other core types in XML format. These .plist files are usually used for storing preferences or application settings.
This XML-formatted property list document is encoded in UTF-8, by default. When you turn your NSString into a property list element, encoding the "é" character replaces it with the UTF-8 Unicode character "\U00e9".