Convert NSString to NSData in Chinese case - ios

everybody, I know this question is lots of people to ask and have lots of answer in stack overflow, but In my case, I try to get the JSON format from here, and code like this:
// Get JSON
NSString* path = #"http://opendata.epa.gov.tw/ws/Data/UV/?format=json";
NSURL* url = [NSURL URLWithString:path];
NSString* jsonString = [[NSString alloc]initWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
NSData* jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary* dic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableLeaves error:nil];
NSArray* arrayResult = dic;
NSDictionary* resultDic = [arrayResult objectAtIndex:0];
NSLog(#"resultDic:%#", resultDic);
NSString* uv = [resultDic objectForKey:#"UVI"];
NSLog(#"UVI:%#", uv);
NSString* publicshedTime = [resultDic objectForKey:#"PublishTime"];
NSLog(#"PublishTime:%#", publicshedTime);
NSLog(#"中文");
I used :
NSString* jsonString = [[NSString alloc]initWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
NSData* jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
But it's not effective to this case, I don't know why.
In console, I can see the Chinese words correctly, and in debugger I can see the "jsonString" content is correct, but I don't know why I convert it to NSData, the content will be wrong, and it output like this :
2014-05-27 03:24:09.307 Tab demo[3014:60b] resultDic:{
County = "\U5609\U7fa9\U5e02";
PublishAgency = "\U4e2d\U592e\U6c23\U8c61\U5c40";
PublishTime = "2014-05-27 03:00";
SiteName = "\U5609\U7fa9";
TWD97Lat = "23,29,52";
TWD97Lon = "120,25,28";
UVI = 0;
}
2014-05-27 03:24:09.308 Tab demo[3014:60b] UVI:0
2014-05-27 03:24:09.308 Tab demo[3014:60b] PublishTime:2014-05-27 03:00
2014-05-27 03:24:09.308 Tab demo[3014:60b] 中文
For sure, the other data without Chinese words is display correctly.
This wrong looks like encoding wrong, but I don't know how to fix it correctly, can anyone tell me the way to fix it, Thanks a lot!

Don't compare contents of objects by their appearance in the console when logged using NSLog. That's unreliable because the algorithm to convert objects into strings is not documented, not strict and is for debugging purposes only.
Compare objects by using the compare: method.

Related

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.

How to parse jsonstring in iOS using objective c?

I have the following json,
{
"method":"login",
"data":{
"username":"abc",
"password":"123"
}
}
I'm using following code to parse it,
NSString* loginMethod= json[#"method"];
NSString* credentials= json[#"data"];
NSLog(#"credentials %#",credentials);
I'm able to get the value for the key data but I'm not be able to get the value of username and password. How to get those values?
change
NSString* credentials= json[#"data"];
to
NSDictionary* credentials= json[#"data"];
then
NSString *username = credentials[#"username"];
if json is in respose data then
NSDictionary *jsonDic = [NSJSONSerialization JSONObjectWithData:request.responseData options:kNilOptions error:&err];
if json is in string then
NSDictionary *jsonDic = [NSJSONSerialization JSONObjectWithData:[str dataUsingEncoding:NSUTF8StringEncoding]; options:kNilOptions error:&err];
NSString* loginMethod= [jsonDic objectForKey:#"method"];
NSString* usename= [[jsonDic objectForKey:#"data"]objectForKey:#"username"];
NSString* password= [[jsonDic objectForKey:#"data"]objectForKey:#"password"];
You could get those values by credentials[#"username"] and credentials[#"password"].
do like
reason it deverives like nested Dictionry
NSString* loginMethod= json[#"method"]; // this is correct
NSString* username= json[#"data"][#"username"];
NSString* password= json[#"data"][#"password"];
Choice -2
NSString* loginMethod= json[#"method"];
// This isNested Dictionary so Do like
NSDictionary* temp= json[#"data"];
NSString *username = temp[#"username"];
NSString * password = temp[#"password"];

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;

What is the best method to break this into usable strings

Whats is the best way to parse this out?
String:
UMversion=2.9&UMstatus=Approved&UMauthCode=152058&UMrefNum=59567592&UMavsResult=Address%3A%20Match%20%26%205%20Digit%20Zip%3A%20Match&UMavsResultCode=YYY&UMcvv2Result=Match&UMcvv2ResultCode=M&UMresult=A&UMvpasResultCode=&UMerror=Approved&UMerrorcode=00000&UMcustnum=&UMbatch=1&UMbatchRefNum=91016&UMisDuplicate=N&UMconvertedAmount=&UMconvertedAmountCurrency=840&UMconversionRate=&UMcustReceiptResult=No%20Receipt%20Sent&UMprocRefNum=&UMcardLevelResult=A&UMauthAmount=10&UMfiller=filled
I get this back from the web service as one big long string. Each of the variables are listed then they have a = sign then what I need to populate the variable with.
I need to get all of this data into variables to check them.
So, how should I go about breaking it down.
Use this kind of code:
NSArray* components = [veryLongString componentsSeparatedByString:#"&"]; // array of strings like "x=y"
NSMutableDictionary* parsedResult = [NSMutableDictionary new];
for (NSString* keyValuePair in components) {
NSArray* keyAndValue = [keyValuePair componentsSeparatedByString:#"="];
NSString* key = keyAndValue[0];
NSString* value = (keyAndValue.count>1) ? keyAndValue[1] : nil;
// remove percent escapes in case we have URL-encoded characters in the value like '%20' and the like
parsedResult[key] = [value stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding] ?: [NSNull null];
}
NSLog(#"dictionary of parameters: %#", parsedResult);
You will end up with a dictionary containing the keys and values extracted from your string.
NSString* firstPass = [sourceString stringByReplacingOccurrencesOfString:#"&" withString:#"\",\""];
NSString* secondPass = [firstPass stringByReplacingOccurrencesOfString:#"=" withString:#"\":\""];
NSString* grandFinale = [NSString stringWithFormat:#"{\"%#\"}"];
NSData* jsonSource = [grandFinale dataUsingEncoding:NSUTF8Encoding];
NSError* error = nil;
NSDictionary* theBiggie = [NSJSONSerialization JSONObjectWithData:jsonSource options:0 error:&error];
I think NSJSONSerialization will automagically fix up the percent encoding. If not, run grandFinale through stringByRemovingPercentEncoding.

Encrypted twitter feed

I'm developing an iOS application , that will take a twits from twitter,
I'm using the following API
https://api.twitter.com/1/statuses/user_timeline.json?include_entities=true&include_rts=true&count=2&screen_name=TareqAlSuwaidan
The problem are feed in Arabic Language ,
i.e the text feed appears like this
\u0623\u0646\u0643 \u0648\u0627\u0647\u0645
How can i get the real text (or how to encode this to get real text) ?
This is not encrypted, it is unicode. The codes 0600 - 06ff is Arabic. NSString handles unicode.
Here is an example:
NSString *string = #"\u0623\u0646\u0643 \u0648\u0627\u0647\u0645";
NSLog(#"string: '%#'", string);
NSLog output:
string: 'أنك واهم'
The only question is exactly what problem are you seeing, are you getting the Arabic text? Are you using NSJSONSerialization to deserialize the JSON? If so there should be no problem.
Here is an example with the question URL (don't use synchronous requests in production code):
NSURL *url = [NSURL URLWithString:#"https://api.twitter.com/1/statuses/user_timeline.json?include_entities=true&include_rts=true&count=2&screen_name=TareqAlSuwaidan"];
NSData *data = [NSData dataWithContentsOfURL:url];
NSError *error;
NSArray *jsonObject = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
NSDictionary *object1 = [jsonObject objectAtIndex:0];
NSString *text = [object1 objectForKey:#"text"];
NSLog(#"text: '%#'", text);
NSLog output:
text: '#Naser_Albdya أيدت الثورة السورية منذ بدايتها وارجع لليوتوب واكتب( سوريا السويدان )
Those are Unicode literals. I think all that's needed is to use NSString's stringWithUTF8String: method on the string you have. That should use NSString's native Unicode handling to convert the literals to the actual characters. Example:
NSString *directFromTwitter = [twitterInterface getTweet];
// directFromTwitter contains "\u0623\u0646\u0643 \u0648\u0627\u0647\u0645"
NSString *encodedString = [NSString stringWithUTF8String:[directFromTwitter UTF8String]];
// encodedString contains "أنك واهم", or something like it
The method call inside the conversion call ([directFromTwitter UTF8String]) is to get access to the raw bytes of the string, that are used by stringWithUTF8String. I'm not exactly sure on what those code points come out to, I just relied on Python to do the conversion.

Resources