How to encode the query part of the NSURL - ios

(iOS 8.0+)
I want to use NSURL to pass some parameters in query part, like this:
NSURLComponents *components = [[NSURLComponents alloc] initWithString:#"ft://market/detail"];
NSDictionary *parameters = #{#"username" : #"高高高", #"from" : #"中国北京"};
NSMutableArray *items = [[NSMutableArray alloc] init];
for (NSString *key in parameters.allKeys) {
[items addObject:[[NSURLQueryItem alloc] initWithName:key value:parameters[key]]];
}
components.queryItems = items;
NSURL *url = components.URL;
NSLog(#"url : %#", url);
However, when I receive the URL and parse it, I find that the Chinese characters passed in the query part are abnormal, and I used NSURLComponents to parse the URL like this:
NSURLComponents *anaComponents = [NSURLComponents componentsWithString:url.absoluteString];
NSMutableDictionary *queryParams = [[NSMutableDictionary alloc] init];
for (NSURLQueryItem *querItem in anaComponents.queryItems) {
[queryParams setObject:querItem.value forKey:querItem.name];
}
NSLog(#"queryParams : %#", queryParams);
The following is the debug log:
url : ft://market/detail?username=%E9%AB%98%E9%AB%98%E9%AB%98&from=%E4%B8%AD%E5%9B%BD%E5%8C%97%E4%BA%AC
queryParams : {
from = "\U4e2d\U56fd\U5317\U4eac";
username = "\U9ad8\U9ad8\U9ad8";
}
The problem now seems to be that there is a problem with encoding and decoding of characters such as Chinese, even if [parameters[key] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]] method is used to encode the query value, it is still wrong when decoding.
The query part I want to parse is like this : #{#"username" : #"高高高", #"from" : #"中国北京"};.
Hope for your helps here, Thanks sincerely.

Related

How to retrieve specific value of key in json?

this is my json content.
[
{
"sha":"30eae8a47d0203ac81699d8fc2ab2632de2d0bba",
"commit":{
"author":{
"name":"Madhura Bhave",
"email":"mbhave#pivotal.io",
"date":"2017-03-23T23:14:32Z"
},
"committer":{
"name":"Madhura Bhave",
"email":"mbhave#pivotal.io",
"date":"2017-03-23T23:14:32Z"
},
"message":"Merge branch '1.5.x'",
}
}
]
and this is my main.i just want to retrieve key value from message and name,email,date from committer dictionary.i got stuck how to do that.
NSMutableArray *CommitArray = [[NSMutableArray alloc] init];
for (NSDictionary *CommitDictionary in CommitJson) {
CommitDict *commitDictObj = [[CommitDict alloc] init];
commitDictObj.message = [CommitDictionary objectForKey:#"message"];
for (NSDictionary *CommitterDictionary in [CommitDictionary objectForKey:#"committer"]) {
Committer *author = [[Committer alloc] init];
author.name = [CommitterDictionary objectForKey:#"name"];
author.email = [CommitterDictionary objectForKey:#"email"];
author.date = [CommitterDictionary objectForKey:#"date"];
}
[CommitArray addObject:commitDictObj];
}
for (int i =0 ; i < [CommitArray count] ; i++){
CommitDict *commitDictObj = [CommitArray objectAtIndex:i];
NSLog(#"Commit Message: %#", commitDictObj.message);
}
return 0;
}
}
i try fetch the json and display it value of message,name,email and date.how can i log the value of message, name, email and date?
Your array contains a dictionary, and that dictionary contains the commit dictionary, not the commit dictionary directly. Replace that part of your code:
for (NSDictionary *CommitDictionary in CommitJson) {
CommitDict *commitDictObj = [[CommitDict alloc] init];
With that:
for (NSDictionary *shaCommitDictionary in CommitJson) {
CommitDict *commitDictObj = [[CommitDict alloc] init];
NSDictionary *CommitDictionary = [shaCommitDictionary objectForKey:#"commit"];
(1) Convert JSON to NSDictionary
NSData *jsonData= ... // Assume you got the data already loaded
NSError *error = nil;
NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
(2) Access the dictionary values (fast enumeration available by now!!
NSString *message = dictionary[#"message"];
NSDictionary *author = dictionary[#"author"];
NSString *name = author[#"author"];
NSString *email = author[#"author"];
NSString *date = author[#"author"];
// OR:
// NSString *name = dictionary[#"author"][#"author"];
// NSString *email = dictionary[#"author"][#"author"];
// NSString *date = dictionary[#"author"][#"author"];
And thats it. I think the tricky thing is to get the JSON Data to the NSDictionary?
See here: https://stackoverflow.com/a/30561781/464016

Corruption of NSString or encoding issue in Objective C

Please see code below:
+ (void)splashDataFromJSON:(NSData *)objectNotation error:(NSError **)error
{
NSError *localError = nil;
NSDictionary *parsedObject = [NSJSONSerialization JSONObjectWithData:objectNotation options:0 error:&localError];
if (localError != nil) {
*error = localError;
}
NSMutableArray* btms = [[NSMutableArray alloc] init];
NSMutableDictionary* btmManufacturerResolutionDictionary = [[BTMCache sharedManager] btmManufacturerResolutionDictionary];
NSArray *results = [parsedObject valueForKey:#"results"];
NSLog(#"Count %d", parsedObject.count);
NSString* imageBaseUrl = [[parsedObject valueForKey:#"general"] valueForKey:#"image_base_url"];
imageBaseUrl = [imageBaseUrl stringByAppendingString:#"hdpi/"];
NSString* splashImageName = [[[parsedObject valueForKey:#"general"] valueForKey:#"splash"] valueForKey:#"img"];
NSString* splashAdvertiserURL = [[[[parsedObject valueForKey:#"general"] valueForKey:#"splash"] valueForKey:#"url"] copy];
NSMutableString* appendedString = [[NSMutableString alloc] init];
for(int i =0 ;i<[splashAdvertiserURL length]; i++) {
char character = [splashAdvertiserURL characterAtIndex:i];
printf(&character);
sleep(0.1);
if (character != "!")
{
[appendedString appendFormat:#"%c", character];
}
}
[[SplashData sharedManager] setSplashAdvertiserURL:appendedString];
[[SplashData sharedManager] setSplashImageName:splashImageName];
splashAdvertiserURL = [[SplashData sharedManager] splashAdvertiserURL];
}
The point of interest is in splashAdvertiserURL. When I receive this data and print it out using po, it comes out as "https://radar.com/ref/go/84/". This is fine and what was expected. When I look at the incoming data in JSONLint it looks like this:
"general": {
"image_base_url": "https:\/\/radar.com\/img\/manufacturers\/",
"splash": {
"img": "image1.png",
"url": "https:\/\/radar.com\/ref\/go\/84\/"
}
},
As you can see, further on I put the NSString into a singleton with an NSString property. Nothing abnormal here. I then proceed to retrieve it to see that all is ok. Further to this the program continues. In another class I wish to retrieve this information, and when I try and do that, it throws EXC_BAD_ACCESS. There appears to be garbage in there.
I then put in a loop in the code as you can see to print out the characters one at a time. Very curiously, when I print that out using po I get:
https://
r
a
d
ar.com/ref/go/8 4!/"
Exactly in that format. If I then proceed to hardcode the string https://radar.com/ref/go/84/ - including escape characters and everything, then all works fine. No issues. If I handle a normal string incoming without escape characters it stores fine in the singleton as well, no issue. enter code here
I am pretty stumped here as to what is going on. Can someone assist?
Thank you
For URL you received as string you need to encode before use it to in your app. Have a look at below code:
NSString *sampleUrl = #"https:\/\/radar.com\/ref\/go\/84\/";
NSString *encodedUrl = [sampleUrl stringByAddingPercentEscapesUsingEncoding:
NSUTF8StringEncoding];

NSURL with JSON returns null

I'm keep getting a (null) error when I try to build my NSURL to open another app.
The URL should be
ms-test-app://eventSourceId=evtSrcId&eventID=13675016&eventType=0&json={"meterresults":[{"clean":"2","raw":"2","status":"0"}]}
but when I try to build my URL it's always null.
At first I thought it has something to do with the URL itself, but it's the same as I got it from the example here.
Another thought was that IOS got some problems with the double quotes in the JSON, but I replaced them with %22, but this doesn't work either.
Here is the code, where I build the URL:
NSString *jsonString = [NSString stringWithFormat:#"{%22meterresults%22:[{%22clean%22:%22%#%22,%22raw%22:%22%#%22,%22status%22:%22%#%22}]}", cleanReadingString, rawReadingString, status];
NSLog(#"JSON= %#",jsonString);
//Send the result JSON back to the movilizer app
NSString *eventSourceId = #"evtSrcId";
NSString *encodedQueryString = [NSString stringWithFormat:#"?eventSourceId=%#&eventID=%d&eventType=0&json=%#",
eventSourceId, _eventId, jsonString];[NSCharacterSet URLQueryAllowedCharacterSet]]
NSString *urlStr = [NSString stringWithFormat:#"%#%#",
[_endpointUrls objectForKey:[NSNumber numberWithInt:(int)_selectedEndpoint]],
encodedQueryString];
NSURL *url = [NSURL URLWithString:urlStr];
I don't know where I'm wrong and I would be glad if someone got any idea.
Thanks in advance.
You should really be using NSURLComponents to create URLs rather than trying to format them into a string.
NSDictionary* jsonDict = #{#"clean": #"2", #"raw": #"2", #"status": #"0"};
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:jsonDict options:0 error:NULL];
NSString* jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSURLComponents* components = [[NSURLComponents alloc] init];
components.scheme = #"ms-test-app";
components.queryItems = #[
[[NSURLQueryItem alloc] initWithName:#"eventSourceId" value:eventSourceId],
[[NSURLQueryItem alloc] initWithName:#"eventID" value:#(_eventId).stringValue],
[[NSURLQueryItem alloc] initWithName:#"json" value:jsonString]
];
NSURL* url = components.URL;
Once you build the URL that way, it becomes apparent that your string doesn't have a host portion (or more accurately, one of your parameters is being used as the host portion).
The other comments about not being able to send JSON as an URL parameter are incorrect. As long as the system on the other side that is parsing the query string can handle it, you can send anything you want as an URL parameter.

iOS parsing img tag found in JSON

I am trying to parse the file location from the following so that image can be displayed. How do I do it?
[
{
"title":"testing barcode display",
"body":"lets see if it renders \r\n\r\n",
"author":"1",
"created":"1373490143",
"nid":"5",
"Barcode":"<img class=\"barcode\" typeof=\"foaf:Image\" src=\"http://mysite.com/sites/default/files/barcodes/95b2d526b0a8f3860e7309ba59b7ca11QRCODE.png\" alt=\"blahimage\" title=\"blahimage\" />"
}
]
I have a table view which displays the title tag. I need to display the entire content in the detail view. I can do everything except the Barcode tag. Please advise.
If it should be done, parse the xml
NSString *xmlString = #"<img class=\"barcode\" typeof=\"foaf:Image\" src=\"http://mysite.com/sites/default/files/barcodes/95b2d526b0a8f3860e7309ba59b7ca11QRCODE.png\" alt=\"blahimage\" title=\"blahimage\" />";
GDataXMLElement *xmlElement = [[GDataXMLElement alloc]initWithXMLString:xmlString error:nil];
NSArray *attributes = [xmlElement attributes];
[attributes enumerateObjectsUsingBlock:^(GDataXMLNode * node, NSUInteger idx, BOOL *stop) {
NSLog(#"%# : %#",node.name,node.stringValue);
}];
OR
NSString *class = [[xmlElement attributeForName:#"class"] stringValue];
NSString *typeOf = [[xmlElement attributeForName:#"typeof"] stringValue];
NSString *src = [[xmlElement attributeForName:#"src"] stringValue];
NSString *alt = [[xmlElement attributeForName:#"alt"] stringValue];
NSString *title = [[xmlElement attributeForName:#"title"] stringValue];
Use json-framework or something similar.
If you do decide to use json-framework, here's how you would parse a JSON string into an NSDictionary:
SBJsonParser* parser = [[[SBJsonParser alloc] init] autorelease];
// assuming jsonString is your JSON string...
NSDictionary* myDict = [parser objectWithString:jsonString];
// now you can grab data out of the dictionary using objectForKey or another dictionary method
You have to convert json string in nsdictionary, so try this
SBJSON *json = [[SBJSON new] autorelease];
NSError *error;
NSDictionary *dict = [json objectWithString:YOUR_JSON_STRING error:&error];
add user this dictionary to display details in tableView

How do I parse a NSString?

I have a string
https://gdata.youtube.com/feeds/api/videos?q=4s-PbMuNooo
I want to get string 4s-PbMuNooo. How do I parse a NSString?
Short answer :
NSString *myString = #"https://gdata.youtube.com/feeds/api/videos?q=4s-PbMuNooo";
NSArray *components = [myString componentsSeparatedByString:#"="];
NSString *query = [components lastObject];
Problems :
1) What if the bit after the q= contains another =
2) What if the q= bit is missing?
A better answer is for you to read the documentation - there are lots of helper methods on NSString that will get you substrings. Look for rangeOfString to find out where the equals would be and subStringWithRange to get the bit you want.
EDIT: Thomas has raised a fair point about URL parsing - see his answer here
A slightly longer but more complete answer. Hope this helps:
NSURL *url = [NSURL URLWithString: #"https://gdata.youtube.com/feeds/api/videos?param1=yeah&param2="];
NSArray *listItems = [[url query] componentsSeparatedByString:#"&"];
NSMutableDictionary *keyValues = [NSMutableDictionary dictionaryWithCapacity:listItems.count];
for (NSString *item in listItems) {
NSArray *keyValue = [item componentsSeparatedByString:#"="];
NSAssert(keyValue.count == 2, #"Key value pair mismatch");
[keyValues setObject:[keyValue objectAtIndex:1] forKey:[keyValue objectAtIndex:0]];
}
NSLog(#"1: %#", [keyValues objectForKey:#"param1"]);
NSLog(#"2: %#", [keyValues objectForKey:#"param2"]);
Like this:
NSArray *listItems = [yourString componentsSeparatedByString:#"="];
NSString *myFinalString=[NSString stringWithString:[listItems objectAtIndex:1]];
I wanted to try this a bit, so here is my code that handles more than one parameters:
NSURL *url = [NSURL URLWithString:#"https://gdata.youtube.com/feeds/api/videos?p=123123&q=234"];
NSArray *queryArray = [[url query] componentsSeparatedByString:#"&"];
for (NSString *queryString in queryArray) {
NSArray *queryComponents = [queryString componentsSeparatedByString:#"="];
if ([[queryComponents objectAtIndex:0] isEqualToString:#"q"]) {
NSLog(#"Found q: %#", [queryString substringFromIndex:2]);
} else {
NSLog(#"Did not find q.");
}
}
The question and its title are badly chosen - the answers are generally right for the more general task of splitting ANY string up, but bad for splitting up URLs as this question is actually about.
Here's how to properly get the values from a URL:
To break up a URL string, first do this:
NSURL *url = [NSURL URLWithString:urlString];
Then retrieve the parameters (the part past the "?") like this:
NSString *query = [url query];
Now you can go ahead and split that query string up using componentsSeparatedByString:#"&" as shown in the other answers.

Resources