JSON Parsing text are In Encoded Form - ios

I am a newbie in iOS development. I parsed a JSON Data From URL like as:
http://www.janvajevu.com/webservice/specific_post.php?post_id=2885
And I parsed a JSON data from it like as:
- (void)viewDidLoad
{
[super viewDidLoad];
[self.webSpinner startAnimating];
NSURL * url=[NSURL URLWithString:[NSString stringWithFormat:#"http://www.janvajevu.com/webservice/specific_post.php?post_id=2885"]];
dispatch_async(kBgQueue, ^{
data = [NSData dataWithContentsOfURL: url];
[self performSelectorOnMainThread:#selector(fetchedData:) withObject:data waitUntilDone:YES];
});
}
-(void)fetchedData:(NSData *)responsedata
{
if (responsedata.length > 0)
{
NSError* error;
self.webDictionary= [NSJSONSerialization JSONObjectWithData:responsedata options:kNilOptions error:&error];
self.webArray=[_webDictionary objectForKey:#"data"];
}
self.headingString=[self.webArray valueForKey:#"post_title"];
NSLog(#"Web String %#",self.headingString);
[self.webSpinner stopAnimating];
self.webSpinner.hidesWhenStopped=TRUE;
NSString *headingString=[NSString stringWithFormat:#"%#",self.headingString];
NSCharacterSet *charsToTrim = [NSCharacterSet characterSetWithCharactersInString:#"() \n\""];
self.headLabel.text=[headingString stringByTrimmingCharactersInSet:charsToTrim];
}
Then I got a response like as means I got label text as:
"\U0aaa\U0abe\U0a97\U0ab2 \U0aae\U0abe\U0ab8\U0acd\U0aa4\U0ab0"
And when I parsed English letters from like as here in my URL "author_name" contain English letters when I parsed it then it print as same as in JSON data but other language means here my URL other data contain Gujarati letters then it is parsed in to decoded or not in Gujarati letters.
Here I not encoded my URL in my code then how it come in this format? Please give me solution for it.

You need to convert ASCII(Unicode Escaped) to Unicode(UTF-8).
check this : http://www.rapidmonkey.com/unicodeconverter/reverse.jsp
In first text box put your \U0aaa... text and click convert you will get what you want.
Now how you can do this in Objective-C:
Try this and let me know what you get.
NSData *data = [self dataUsingEncoding:[NSString defaultCStringEncoding]];
NSString *unicodeString = [[NSString alloc] initWithData:data encoding:NSNonLossyASCIIStringEncoding];
self.headLabel.text = asciiString;

try this
NSString *aDescription = self.webArray[0][#"post_title_slug"];
NSString *aTitle = [[aDescription stringByRemovingPercentEncoding] stringByReplacingPercentEscapesUsingEncoding:NSASCIIStringEncoding];

Related

How can I use NSJSONSerialization with special characters like "ñ"?

I'm using NSJSONSerialization to parse Google suggestions.
The query "f" returns these suggestions:
["f",["facebook","flipkart","fox news","forever 21","friv","fandango","fedex","fitbit","food near me","flights"]]
The parser works fine but when there are special characters like "ñ" for the query "fac":
["fac",["facebook","facebook search","fac","facebook app","facebook lite","facebook login","facebook logo","facebook messenger","facetime","facebook en español"]]
It throws an exception:
Error Domain=NSCocoaErrorDomain Code=3840 "Unable to convert data to string around character 139." UserInfo={NSDebugDescription=Unable to convert data to string around character 139.}
Any ideas? I tried all different reading options but none of them works.
#pragma mark -
- (void)request:(NSString *)text
{
NSMutableArray *items = [[NSMutableArray alloc] init];
NSString *query = [text stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSString *languageCode = [[NSLocale preferredLanguages] firstObject];
if (!languageCode) {
languageCode = #"en";
}
NSString *URLString = [NSString stringWithFormat:#"http://suggestqueries.google.com/complete/search?q=%#&client=firefox&hl=%#", query, languageCode];
NSError *downloadError = nil;
NSData *JSONData = [NSData dataWithContentsOfURL:[NSURL URLWithString:URLString] options:0 error:&downloadError];
if (!downloadError && JSONData) {
NSError *parseError = nil;
id object = [NSJSONSerialization JSONObjectWithData:JSONData options:NSJSONReadingMutableContainers error:&parseError];
if (!parseError && object) {
if ([object isKindOfClass:[NSArray class]]) {
NSArray *objects = (NSArray *)object;
NSArray *texts = [objects objectAtIndex:1];
for (NSString *text in texts) {
SNGoogleItem *item = [[SNGoogleItem alloc] initWithText:text];
[items addObject:item];
}
[_delegate google:self didRespondWithItems:items];
}
else {
[_delegate google:self didRespondWithItems:items];
}
}
else {
[_delegate google:self didRespondWithItems:items];
}
}
else {
[_delegate google:self didRespondWithItems:items];
}
}
JSONSerialization supports all the encodings in JSON spec, says Apple documentation.
You didn't provide much info about the encoding scheme of your data but I guess you use nonLossyASCII or something like that, which is not supported by JSONSerialization.
Here is how I convert data to/from JSON:
let rawString = "[[\"facebook en español\"]]"
// if I use String.Encoding.nonLossyASCII below, I get the error you are getting
let data = rawString.data(using: String.Encoding.utf8)
let dict = try! JSONSerialization.jsonObject(with: data!)
let convertedData = try! JSONSerialization.data(withJSONObject: dict)
let convertedString = String(data: convertedData, encoding: String.Encoding.utf8)!
// now convertedString contains "ñ" character
This will convert whatever encoding used to UTF8:
NSData *JSONData = [NSData dataWithContentsOfURL:[NSURL URLWithString:URLString] options:0 error:&downloadError];
NSString *convertedJSONString; BOOL usedLossyConversion;
[NSString stringEncodingForData:JSONData encodingOptions:0 convertedString:&convertedJSONString usedLossyConversion:&usedLossyConversion];
NSData *convertedJSONData = [convertedJSONString dataUsingEncoding:NSUTF8StringEncoding];
Now, it works!

How to parse JSON data from textual file in Objective-C

I know, JSON parsing questions are asked over and over again, but still I can't find any answer to this one.
I've been trying to read and parse a textual JSON file using NSJSONSerialization to no avail.
I've tried using the same JSON data from a NSString and it did work.
Here's the code:
NSError *error;
NSString *jsonString1 = [NSString stringWithContentsOfFile:jsonFilePath
encoding:NSUTF8StringEncoding
error:&error];
NSData *jsonData1 = [jsonString1 dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *jsonObject1 = [NSJSONSerialization JSONObjectWithData:jsonData1
options:0
error:&error];
NSString *jsonString2 = #"{\"key\":\"value\"}";
NSData *jsonData2 = [jsonString2 dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *jsonObject2 = [NSJSONSerialization JSONObjectWithData:jsonData2
options:0
error:&error];
- The text file contains one line: {"key":"value"}
- jsonString1 = #"{"key":"value"}"
- jsonString2 = #"{\"key\":\"value\"}"
- jsonData1 is 23 bytes in size
- jsonData2 is 15 bytes in size
- jsonObject1 is nil and I get error code 3840
- jsonObject2 is a valid dictionary
Seems like the problem is with reading the file, since the NSStrings and NSDatas differ, but what am I doing wrong here and how can I fix it?
Most likely you file contains some unprintable characters (e.g. \0) that trigger the failure. Printing the error message will tell you at what position the first invalid characters occurs.
For example, try printing "{\"key\":\u{0000}\"value\"}" and you'll seem to get a valid JSON, however decoding it fails.
I always do a check on the return value when doing anything with NSUTF8StringEncoding and if nil, then try NSASCIIStringEncoding:
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
if (jsonString == nil) {
jsonString = [[NSString alloc] initWithData:jsonData encoding:NSASCIIStringEncoding];
}
return jsonString;

NSUTF8StringEncoding gives me this %0A%20%20%20%20%22http://example.com/example.jpg%22%0A

I'm trying to load pictures from twitter. If i just use the URL in the json results without encoding, in the dataWithContentsOfURL, I get nil URL argument. If I encode it, I get as follow's
%0A%20%20%20%20%22http://example.com/example.jpg%22%0A.
I know I can use rangeOfString: or stringByReplacingOccurrencesOfString: but can I be sure that it will always be the same, is there another way to handle this, and why is this happening to my twitter response and not my instagram response?
I have also tried
stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]
and it does nothing.
This is the URL directly from the json...
2013-11-08 22:09:31:812 JaVu[1839:1547] -[SingleEventTableViewController tableView:cellForRowAtIndexPath:] [Line 406] (
"http://pbs.twimg.com/media/BYWHiq1IYAAwSCR.jpg"
)
Here is my code
if ([post valueForKeyPath:#"entities.media.media_url"]) {
NSString *twitterString = [[NSString stringWithFormat:#"%#", [post valueForKeyPath:#"entities.media.media_url"]]stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
twitterString = [twitterString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog(#"%#", twitterString);
if (twitterString != nil){
NSURL *twitterPhotoUrl = [NSURL URLWithString:twitterString];
NSLog(#"%#", twitterPhotoUrl);
dispatch_queue_t queue = kBgQueue;
dispatch_async(queue, ^{
NSError *error;
NSData* data = [NSData dataWithContentsOfURL:twitterPhotoUrl options:NSDataReadingUncached error:&error];
UIImage *image = [UIImage imageWithData:data];
dispatch_sync(dispatch_get_main_queue(), ^{
[streamPhotoArray replaceObjectAtIndex:indexPath.row withObject:image];
cell.instagramPhoto.image = image;
});
});
}
}
The log output you show appears to be an array, since it has parentheses with the string on a separate line.
You shouldn't need to encode the string if it's already a valid URL string and in fact doing so is wrong and will break things.
%0A%20%20%20%20%22 stands for a \n followed by 4 spaces and then ". This is in accordance with the description in the console. Have you used NSJSONSerialization to obtain the URL from JSON data?
Not the answer rather a step in solving the error,: Change your code to this and post the output. Combining several method calls in one makes debugging harder.
NSLog(#"post: '%#", post);
NSString * twitterString;
twitterString = [post valueForKeyPath:#"entities.media.media_url"];
NSLog(#"twitterString 1: '%#", twitterString);
twitterString = [twitterString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSLog(#"twitterString 2: '%#", twitterString);
twitterString = [twitterString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog(#"twitterString 3: '%#", twitterString);
BTW, [NSString stringWithFormat:#"%#"... is not necessary.

JSONObjectWithData and umlauts

I am using a service (not mine) that supplies JSON-formatted data. When I try to parse the data with JSONObjectWithData:options:error:, it returns nil if there is an umlaut (ö, for example). It works fine if there are no umlauts or other special characters.
The person running the service says the data is encoded as ISO-8859-1 (not UTF-8).
Is there anything I can do at my end to get such data to parse correctly?
Try with below piece of code:
NSError *error;
NSString *string = [NSString stringWithContentsOfURL:webURL encoding:NSISOLatin1StringEncoding error:&error];
NSData *utf8Data = [string dataUsingEncoding:NSUTF8StringEncoding];
id jsonObject = [NSJSONSerialization JSONObjectWithData:utf8Data options:kNilOptions error:&error];
if (error) {
//Error handling
} else {
//use your json object
}
if you have NSData with latin1 (ISO-8859-1) then you may want to convert it to UTF-8 first, like this:
const char latin1[1] = {196}; // iso-8859-1 umlaut character code
NSData *latin1Data = [NSData dataWithBytes:latin1 length:1];
NSString* utfstr = [[NSString alloc] initWithCString:latin1Data.bytes encoding:NSISOLatin1StringEncoding];
NSLog(#"%#",utfstr);

Adding bounds to google maps search string causes nil results

I added a search box to my mapping app a little while back which was doing very simple address searching with minimal options.
http://maps.googleapis.com/maps/api/geocode/json?address=sydney+grove&sensor=true
I've just added bounds parameters using the current screen viewport like this
http://maps.googleapis.com/maps/api/geocode/json?address=sydney+grove&bounds=51.198083,-0.830125|51.799930,0.576125&sensor=true
it returns a result when pasted into a browser but always a nil result if entered in code (jsonResponse always equals nil)
-(void) doGeocodingBasedOnStringUsingGoogle:(NSString*) searchString {
GMSCoordinateBounds* bounds=[[self datasource] searchBounds];
//CREATE LOOKUP STRING
NSString *lookUpString = [NSString
stringWithFormat:#"http://maps.googleapis.com/maps/api/geocode/json?
address=%#&bounds=%f,%f|%f,%f&sensor=true",
searchString,
bounds.southWest.latitude,
bounds.southWest.longitude,
bounds.northEast.latitude,
bounds.northEast.longitude];
lookUpString = [lookUpString stringByReplacingOccurrencesOfString:#" "
withString:#"+"];
//SEARCH FOR RESULTS
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
NSError *error = nil;
NSData *jsonResponse = [NSData dataWithContentsOfURL:[NSURL URLWithString:lookUpString]];
if (jsonResponse) {
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:jsonResponse options:kNilOptions error:&error];
self.searchResults = [jsonDict valueForKey:#"results"];
}
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableview reloadData];
});
});
}
This code was fine before I added the bounds condition and is fine if I remove so I'm really out of ideas
I think you need to replace the | with a %7C, for example see here:
How to make an NSURL that contains a | (pipe character)?
As mentioned in the comments on the answer, you could look into using stringByAddingPercentEscapesUsingEncoding for a method to escape the URL for you (so eg you wouldn't need to replace spaces with a +, etc).

Resources