Correctly Handle UTF-8 In JSON on iOS - ios

I'm receiving some JSON that has weird UTF-8 strings. Eg:
{
"title": "It\U2019s The End";
}
What's the best way to handle this data so that it can be presented in a readable way? I'd like to convert that \U2019 into the quote mark that it should represent.
Edit:
Assume I have parsed the string into a NSString* jsonResult
Edit 2: I'm receiving the JSON through AFNetworking:
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSString* jsonResult = [JSON valueForKeyPath:#"title"];
} failure:nil];

Update:
Kurt has brought to attention that AFJSONRequestOperation uses NSJSONSerialization under the hood. As such, it's probably the case that your JSON is invalid (as mentioned below, there shouldn't be a ;, and the U should be a lowercase u. This was mentioned in the original answer below.
It's part of the way JSON is able to store its data. You will need to pass your JSON string through a JSON parser, then you will be able to extract your string correctly.
Note: The JSON you've posted above is invalid, there shouldn't be a semi-colon at the end, and the U should be a lower-case u; the example below has a modified JSON string
NSString* str = #"{\"title\": \"It\\u2019s The End\"}";
NSError *error = nil;
NSData* data = [str dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *rootDictionary = [NSJSONSerialization JSONObjectWithData:data
options:0
error:&error];
if (error) {
// Handle an error in the parsing
}
else {
NSString *title = [rootDictionary objectForKey:#"title"];
NSLog(#"%#", title); //Prints "It’s The End"
}

Related

Parsing JSON Help IOS

I currentley have a jSON file which is created a by a script which can be seen here: http://ddelay.co.uk/bus/output.json
I currently have managed to setup the following to grab the JSON which works, i just cannot figure how to grab the data to assign it :/
-(void)makeStopRequests{
NSURL *url = [NSURL URLWithString:#"http://ddelay.co.uk/bus/output.json"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//AFNetworking Asynchronous Task
AFJSONRequestOperation *operation = [AFJSONRequestOperation
JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id responseObject)
{
NSLog(#"JSON RESULT %#", responseObject);
self.stopArray = [responseObject objectForKey:#"stop_name"];
[self.tableView reloadData];
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id responseObject)
{
NSLog(#"Request Failed: %#, %#", error, error.userInfo);
}];
[operation start];
}
I hope somebody can guide me through how I would select the data,
Thank you.
Damien
I would recommend just using something as simple as NSJSONSerialization, which is built into iOS after iOS 5 (may have been earlier, but not too sure).
Just get the data from the request and then parse that into a dictionary with the following code
NSDictionary *dict= [NSJSONSerialization JSONObjectWithData:webData options:NSJSONReadingMutableLeaves error:nil];
get the data using the standard built in networking structure as well
NSURLRequest *someRequest = [[NSURLRequest alloc] initWithURL:someURL cachePolicy:NSURLRequestReloadRevalidatingCacheData timeoutInterval:10.0];
NSURLConnection *someConnection= [[NSURLConnection alloc] initWithRequest:someRequest delegate:self];
And then do whatever appropriate delegation and data processing. Read the documentation to get more details
You are using AFNetworking and it provides you the response object. That is already being cast to Objective c object.
You can simply assign it to NSArray or NSDictionary like this
NSArray *array = (NSArray*)responseObject;//if your json returns an array
NSDictionay *dict (NSDictionary*)responseObject;//if json returns dictionary.
This url returns JSON in this format;
[ {
"service":"22",
"provider":"First in Yorkshire",
"dest":"Nether Edge to Woodhouse",
"dest URL":"/web/public_service_stops.asp?service=22&operatorid=31&systemid=30&goingto=Woodhouse"
},
{
"service":"22",
"provider":"First in Yorkshire",
"dest":"Barnsley to Rotherham",
"dest URL":"/web/public_service_stops.asp?service=22&operatorid=31&systemid=30&goingto=Rotherham"
}
]
Which actually is an array of dictionaries so to access data you have to loop like this.
NSArray *jsonResponse = (NSArray*)responseObject;
for (NSDictionary *dic in jsonResponse){
NSString *service = [dic valueForKey:#"service"];
NSString *provider = [dic valueForKey:#"provider"];
//Same for others
//It will better you create calss with these properties and then add that object to an Array, and on reloading data in table get that object from array in cellForRowAtIndexPath and use requried property to populate your data.
//Or if you just want to use stop name add stop name to array and use it.
NSString *stopName =[dic valueForKey:#"stop_name"];
//[dataArray addObject:stopName]; in case you want to use only stop name
}
Here's minimal code:
self.stopArray = responseObject;
for (NSDictionary *stopDict in self.stopArray) {
NSString *service = [stopDict objectForKey:#"service"];
NSString *provider = [stopDict objectForKey:#"provider"];
NSString *dest = [stopDict objectForKey:#"dest"];
NSString *destURL = [stopDict objectForKey:#"dest URL"];
// do something with this data
}
For anything more complex than this, you'll probably want to make your own data class, so you don't have to parse through dictionaries and arrays in your table view delegate methods.

Json Parsing Failed

I am creating a simple Login page. In my project I want to parse the json string. But it gives me following error.
-JSONValue failed. Error trace is: (
"Error Domain=org.brautaset.JSON.ErrorDomain Code=4
\"Valid fragment, but not JSON\"
UserInfo=0xa6e70a0 {NSLocalizedDescription=Valid fragment, but not JSON}"
In my code if I am putting another json string than it is working. And also my original json string is giving me the data in browser. So what to do?
My Code is:
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://dev.bevbucks.com/gbs/api.json/token?user=rverma#prismetric.com&pwd=verma!pris"]];
NSURLResponse *response = nil;
NSError *error = nil;
//getting the data
NSData *newData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
//json parse
NSString *responseString = [[NSString alloc] initWithData:newData encoding:NSUTF8StringEncoding];
NSDictionary *jsonObject = [responseString JSONValue];
NSLog(#"type : %#", jsonObject );
The returned string:
"60ee094456b6fc03f386af50c443b471"
Isn't valid JSON, and should at least be:
[ "60ee094456b6fc03f386af50c443b471" ]
So there is a bug in the server, and not your code. If you cannot get this bug fixed then you're going to have to workaround it.
From JSON.org:
JSON is built on two structures:
A collection of name/value pairs. In various languages, this is
realized as an object, record, struct, dictionary, hash table, keyed
list, or associative array.
An ordered list of values. In most
languages, this is realized as an array, vector, list, or sequence.

Parsing JSON response

I am using AFJSONRequestOperation to request a remote API:
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
//Remove the SVProgressHUD view
[SVProgressHUD dismiss];
//Check for the value returned from the server
NSData *jsonData = [JSON dataUsingEncoding:NSUTF8StringEncoding];//This line cause crash
NSArray *arr = [NSJSONSerialization JSONObjectWithData:jsonData
options:0
error:nil];
loginDic=[[NSDictionary alloc]init];
loginDic=[arr objectAtIndex:0];
NSLog(#"%#",loginDic);
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"Request Failed with Error: %#", [error.userInfo objectForKey:#"NSLocalizedDescription"]);
}];
[operation start];
[SVProgressHUD showWithStatus:#"Loading"];
However, the app crashes and I am getting this error:
[__NSCFDictionary dataUsingEncoding:]: unrecognized selector sent to instance
Here is an NSLog for the JSON object returned:
Result = (
{
operation = 5;
result = 1;
}
);
Am I missing something, because I think that I am not parsing correctly the JSON object. Please correct me.
It looks like AFJSONRequestOperation is deserializing JSON to a dictionary for you, and then you're trying to do it again. JSON is an NSDictionary but you're calling an NSString method.
Remove all of this code:
NSData *jsonData = [JSON dataUsingEncoding:NSUTF8StringEncoding];//This line cause crash
NSArray *arr = [NSJSONSerialization JSONObjectWithData:jsonData
options:0
error:nil];
loginDic=[[NSDictionary alloc]init];
loginDic=[arr objectAtIndex:0];
And replace it with:
loginDic = [[JSON objectForKey:#"Result"] lastObject];
(That'll work safely without checking array bounds, but assumes that there's only one element in the array.)
The object you get in the success block is already parsed by AFJSONRequestOperation.
In your case you get a NSDictionary object.
You can check the class of the object using the isKindofClass-method:
if ([JSON isKindOfClass:[NSDictionary class]]) {
NSDictionary* dict = (NSDictionary*)JSON;
...
}

access NSMutableDictionary value without key?

quite new to iOS development and objective-c at the same time. I have the following method:
-(NSMutableArray *)fetchDatabaseJSON{
NSURL *url = [NSURL URLWithString:#"http://www.ios.com/ios/responseScript.php"];
NSError *error = nil;
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:NULL error:&error];
//jsonArray = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
//NSLog(#"Array: %#",[jsonArray objectAtIndex:0]);
jsonDictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
NSLog(#"Dictionary: %#", jsonDictionary);
return jsonArray;
}
Now the NSLog shows this:
2013-02-03 19:15:37.081 TestConnection[24510:c07] Dictionary: (
Bannana,
Apple,
SomeCheese )
From what I understand that whatever is inside the dictionary doesn't have key-value. How can this be? and how can I fix it? I want to be able to have keys to ease operations on dictionary.
Regards,
JSONObjectWithData may return an NSArray or NSDictionary, depending on the JSON data you give it. If your JSON string is an array, you will have an NSArray. If your JSON data is a dictionary, you will get an NSDictionary.
Convert your JSON data (your data variable) to string and print it out with NSLog. To convert NSData to NSString, use something like:
NSString *myString = [[NSString alloc] initWithData:myData encoding:NSUTF8StringEncoding];
If you print it out and see a JSON array, you simply don't have a dictionary there.. If you can alter the server-code that generates the JSON, you may be able to change that.
One more thing I noticed, you assume that the returning container is mutable. If I'm not mistaken, you need to use an option like NSJSONReadingMutableContainers in the options parameter of JSONObjectWithData to get that.
One last tip, if you want to check in code if you have an NSArray (or NSDictionary), use something like:
if ([obj isKindOfClass:[NSArray class]]) {...}

stuck to parse a JSON returned from server, ios

I am doing an authentication by using AFNetworking like below
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
// Parsing will be here
{
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"ERROR :jason is %#",JSON);
}];
[client enqueueHTTPRequestOperation:operation];
Below is a JSON which received from server
{
"first_name" = A;
"last_name" = B;
}
Question :
How can a parse this JSON in ios. I am stuck because the return from server does not have any tag at all. If its format was
{
"user": {
"first_name": "A",
"last_name": "B",
}
}
I could parse by doing the following
NSArray *userList = [[NSArray alloc] init];
userList = [JSON objectForKey:#"results"];
Any ideas?
"Tag" is not in the terminology of JSON. The complex structure of JSON is negotiated between the sender and receiver (or simply dictated by the sender) and need not follow any particular outline, so long as it parses correctly.
The first quasi-JSON string you quoted would (if it were valid JSON) presumably identify the first and last name of an individual, and you would presumably know that it was a "user" identity, and what user it identified, from the context.
In general, you must approach a JSON string as an onion, peeling one layer at a time. In the case of your first string there is only one layer, an "Object" that maps to an NSDictionary. So, having received the object (and, if necessary, verified that it is indeed an NSDictionary using isKindOfClass, you would cast the id value to an NSDictionary and proceed to use objectForKey or some such to access the values within.
You should utilize the new JSONSerialization class available in iOS5 which makes JSON easy to consume. Below is a quick example grabbing your json and parsing it in the fetchedData method. Resources listed below
//CALL dataWithContentsOfURL ONCE DATA HAS BEEN RECEIVED YOU CAN PARSE THE JSON:
NSError *error = nil;
NSData* data = [NSData dataWithContentsOfURL:kURL options:NSDataReadingUncached error:&error];
if (error) {
NSLog(#"%#", [error localizedDescription]);
} else {
NSLog(#"Data has loaded successfully.");
}
//MORE CODE HERE?
- (void)fetchedData:(NSData *)responseData {
_yourObjectArray = [[NSMutableArray alloc] init];
//parse out the json data
NSError* error;
NSArray* json = [NSJSONSerialization JSONObjectWithData:responseData //1
options:kNilOptions
error:&error];
for(int i=0; i<[json count]; i++){
YourObject *yObject = [[YourObject alloc]init];
NSDictionary* rawData = [json objectAtIndex:i]; //2
yObject.FirstName = [rawData objectForKey:#"first_name"];
yObject.LastName = [rawData objectForKey:#"last_name"];
[_yourObjectArray addObject:yObject];
}
}
SOURCES:
http://developer.apple.com/library/ios/#documentation/Foundation/Reference/NSJSONSerialization_Class/Reference/Reference.html
http://www.raywenderlich.com/5492/working-with-json-in-ios-5

Resources