Parsing JSON string with different local (no english) - ios

I got below JSON string, i facing issue parsing because it contains non english local:
{"error":0,"token":"59188a107d705f8c51585d719769e0642ce98b79d86fdace30dbc58efba301cc","status":"200","messages":[{"update_time":"2012-03-31
22:50:13","seq":"497","lng":58.4235,"msg":"hhhh : ≈∏?≈∏?
ÿ™ÿ™ÿߟ?ÿ™ ","lat":23.5866}],"error_msg":""}
i'm trying with below code:
NSError* error;
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:responseData //1
options:kNilOptions
error:&error];
it works fine if it's in English only, how could I parse non english local in JSON.

From the docs:
The data must be in one of the 5 supported encodings listed in the JSON specification: UTF-8, UTF-16LE, UTF-16BE, UTF-32LE, UTF-32BE. The data may or may not have a BOM. The most efficient encoding to use for parsing is UTF-8, so if you have a choice in encoding the data passed to this method, use UTF-8.
Since your string does not appear correctly in Safari, I suspect that it is not encoded in one of these formats. You would need to re-encode your data into a legal JSON encoding.

Related

JSONSerilazation not working while parsing JSON object

I am getting an error while parsing the NSData I got from a server.
I am unable get the NDIctinory.
I am getting the error "No string key for value in object"
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:[body dataUsingEncoding:NSUTF8StringEncoding]
options:kNilOptions
error:&error];
Could someone help me with this issue?
The error message says that in the object (that's what JSON calls a dictionary) there is a key that is not a string, i. e. a number or another object. This is invalid.
From RFC7159, 4:
An object structure is represented as a pair of curly brackets
surrounding zero or more name/value pairs (or members). A name is a
string.
Therefore you will have an invalid JSON. Change that, if possible. Aditionally you can post the whole JSON in your Q. (Not in a comment to this A.)

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.

iOS RestKit 0.2 What is the best way to parse local Json

I wave read many articles about parsing a json via an Http request but almost none answers the question about what is the most straight forward way to parse o local json string. I found some deferent solutions here Deserializing local NSString of JSON into objects via RestKit (no network download) some of them work some others don't. Is there any "official" RestKit support for local JSON string deserialization?
Fortunately Apple provides "NSJSONSerialization" class from iOS 5.0. to serialise your data.
Step 1 : convert your local JSON string to "NSData"
NSString *strLocalJSON = #"{data= "some data"}"; //just for ex. may not be valid one
NSData *dataJSON = [str dataUsingEncoding:NSUTF8StringEncoding];
Step2:
id jsonobject= [NSJSONSerialization JSONObjectWithData:dataJSON options:NSJSONReadingMutableContainers error:nil]; // resulting object may contain Dictionary or Array depends on your localjson
for further info refer https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSJSONSerialization_Class/Reference/Reference.html
If your JSON is in a file then you use a file:// NSURL when you create your RestKit object manager. Everything else works as normal.
If the JSON is already in code, then you should save it to a file, or why are you needing to do any mapping? Anyway, you could use a combination of NSJSONSerialization and RKMappingOperation.

Determining Issue With Retrieving JSON from URL in iPhone

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

IOS cannot decode emoji unicode in json format correctly, and Emoji icons are displayed as squares

I am working on an iPhone app which allows people to send messages with Emoji icons. I saved the icon in Mysql with charset utf8mb4 and collation utf8mb4_unicode_ci, and all the emoji icons is saved correctly in my database. However, when I return json back to the client (php json_encode), the Emoji is encoded as something like this: '\ud83d\ude04', and iPhone displays it as a square. However, if I return as XML, the Emoji Icon won't become unicode like this: '\ud83d\ude04', it will just be the icon.
I am wondering if this is an issue on my server, or on my client. If it is my client, how can object c decode it correctly.
Can someone please help?
Thanks
"\ud83d\ude04" is the JSON Unicode escape sequence for U+D83D U+DE04, which is the "surrogate pair" for the Unicode U+1F604 (SMILING FACE WITH OPEN MOUTH AND SMILING EYES).
But NSJSONSerialization decodes this correctly, as can be seen in the following example:
const char *jsonString = "{ \"emoji\": \"\\ud83d\\ude04\" }";
NSLog(#"JSON: %s", jsonString);
NSData *jsonData = [NSData dataWithBytes:jsonString length:strlen(jsonString)];
NSError *error;
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
self.myLabel.text = [jsonDict objectForKey:#"emoji"];
NSLog(#"Emoji: %#", self.myLabel.text);
Output:
JSON: { "emoji": "\ud83d\ude04" }
Emoji: 😄
and the Emoji symbol is also displayed correctly (tested with iPhone device and Simulator).
Please follow following steps:
Convert Emoji characters to base64 and send to server using Json.
On server side save base64 in database without decode.
When you want to display Emoji on Application then retrieve same base64 data from server.
Decode retrieve string and display on app.
Your Emoji character will display properly.
Note: When you want to Show on webPage then Decode data when you display data on WebPage.
Our team fixed this problem by transfer utf data to server, saving them in mysql utf8mb4 codepage and receiving with base64. Server convert saved data to base64 on demand.

Resources