How to convert escaped JSON-string to NSString? - ios

I am working with a http-server, which return JSON-string in response body:
"Some text.\nSome text.\n\t\"Some text in quotes.\""
I need remove quotes in the start and end of string, and I need unescape special symbols. I make category for NSString, but I think that it is wrong implementation: https://gist.github.com/virasio/59907e087f859e6c1723
I have other idea. I can use NSJSONSerialization:
NSString *sourceString = #"\"Some text.\\nSome text.\\n\\t\\\"Some text in quotes.\\\"\"";
NSString *jsonObject = [NSString stringWithFormat:#"{ \"value\" : %# }", sourceString];
NSDictionary *object = [NSJSONSerialization JSONObjectWithData:[jsonObject dataUsingEncoding:NSUTF8StringEncoding options:0 error:NULL]];
NSString *result = [object objectForKey:#"value"];
But... It is not good too.

By default, Foundation will only parse JSON objects or arrays, but it can parse strings, numbers and booleans if you tell it to accept JSON fragments:
NSData *data = [#"\"Some text.\\nSome text.\\n\\t\\\"Some text in quotes.\\\"\""
dataUsingEncoding:NSUTF8StringEncoding];
id result = [NSJSONSerialization JSONObjectWithData:data
options:NSJSONReadingAllowFragments
error:NULL];
NSLog(#"[result class] = %#", [result class]);
NSLog(#"result = %#", result);
Yields:
[result class] = __NSCFString
result = Some text.
Some text.
"Some text in quotes."
This is actually one of the cases where passing error really helps. I had tried without passing NSJSONReadingAllowFragments and got a very clear error message:
Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (JSON text did not start with array or object and option to allow fragments not set.)

Related

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;

how to remove the \ character

I have a string with the following information:
\"[{\"CodRTA\":\"1\",\"MenssRTA\":\"messaje error\",\"Resp\":\"\"}]\"
and I need to delete the character \ I'm trying to remove as follows, but the character is using the system and leaves close the line of code
NSString *filtered = [[[restConnection stringData] componentsSeparatedByString:#"\"] componentsJoinedByString:#""];
NSLog(#"filtrado: %#", filtered);
the error is
Expected ']' in this part : componentsSeparatedByString:#"\"]
Its looks like JSON data, instead interfering into JSON, just convert JSON string to NSData and then into NSDictionary or NSArray
NSString *jsonString = #"[{\"CodRTA\":\"1\",\"MenssRTA\":\"messaje error\",\"Resp\":\"\"}]";
NSData *data = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSArray *array = [NSArray arrayWithArray:json];
Now if you do following NSLog statement
NSLog(#"%#",[[json firstObject] objectForKey:#"CodRTA"]);
Result would be another NSDictionary.
{
CodRTA = 1;
MenssRTA = messaje error;
Resp = "";
}
Btw, I formatted your JSON response, its look like this,
Someting like that
string = [string stringByReplacingOccurrencesOfString:#"\\" withString:#""];
use this code
NSString *str=#"[{\"CodRTA\":\"1\",\"MenssRTA\":\"messaje error\",\"Resp\":\"\"}]";
NSString *filtered = [[str componentsSeparatedByString:#"\\"] componentsJoinedByString:#""];
NSLog(#"filtrado: %#", filtered);

Parse JSON data is returning null value

I am getting JSON data with below code as string. But really very confusing to solve this
NSString *htmlSTR = [[NSString alloc] initWithData:self.receivedData
encoding:NSUTF8StringEncoding];
NSLog(#"userdetail :%#" , htmlSTR);
But i need to parse the Id only.
I parsed with the code of
NSDictionary *JsonDict = [NSJSONSerialization JSONObjectWithData:self.receivedData options: NSJSONReadingMutableContainers error: &e];
NSLog(#"json %#",jsonArr1);
NSString *string=[JsonDict valueForKey:#"Id"];
But its returning null value for string, even for integer it is returning numeric zero
userdetail : {"Country":"Afghanistan","CreatedBy":"raje#gmail.com","FirstName":"rajeev","Gender":"M","LastName":"leader","ModifiedBy":"raje#gmail.com","Password":"asdf","emails":"raje#gmail.com","id":32}
This is the first time am trying this thing, help me to solve this.Sorry for bad formatting.
only change this line .
NSString *string=[JsonDict valueForKey:#"Id"];
TO
NSString *string=[JsonDict valueForKey:#"id"];
Hope this works for you.

NSData to NSString with JSON response

NSData* jsonData is the http response contains JSON data.
NSString* jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSLog(#"jsonString: %#", jsonString);
I got the result:
{ "result": "\u8aaa" }
What is the proper way to encoding the data to the correct string, not unicode string like "\uxxxx"?
If you convert the JSON data
{ "result" : "\u8aaa" }
to a NSDictionary (e.g. using NSJSONSerialization) and print the dictionary
NSError *error;
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
NSLog(#"%#", jsonDict);
then you will get the output
{
result = "\U8aaa";
}
The reason is that the description method of NSDictionary uses "\Unnnn" escape sequences
for all non-ASCII characters. But that is only for display in the console, the dictionary is correct!
If you print the value of the key
NSLog(#"%#", [jsonDict objectForKey:#"result"]);
then you will get the expected output
說
I don't quite understand what the problem is. AFNetworking has given you a valid JSON packet. If you want the above code to output the character instead of the \u… escape sequence, you should coax the server feeding you the result to change its output. But this shouldn't be necessary. What you most likely want to do next is run it through a JSON deserializer…
NSDictionary * data = [NSJSONSerialization JSONObjectWithData:jsonData …];
…and you should get the following dictionary back: #{#"result":#"說"}. Note that the result key holds a string with a single character, which I'm guessing is what you want.
BTW: In future, I suggest you copy-paste output into your question rather than transcribing it by hand. It'll avoid several needless rounds of corrections and confusion.

NSJSONSerialization sometimes returns null in async request

I've been developing app, that makes asynchronous requests for JSON type of data. Lately, I found strange bug in my code and I can't tell why it is happening.
Ok to the code!
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSError *error=nil;
result = [NSJSONSerialization JSONObjectWithData:retrievedData options:kNilOptions error:&error];
NSLog(#"Result %#",result);
NSLog(#"Retrieved data %#",retrievedData);
}
Result is NSDictionary, retrievedData is NSMutableData.
99% of the time, it works fine, connectionDidFinishLoading gets called, and my result is populated. However, in that 1% of the time retrieved data is filled with data, but my result is null.(as you can see on the picture. Could anyone help me please?
Edit: I get following error
Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (Garbage at end.) UserInfo=0x753e5c0 {NSDebugDescription=Garbage at end.}
It would help if you take a look at the error first, to see if that gives any indication of what is wrong.
[edit]
Your error mentions the reason: Garbage at end..
The response from the webserver is not valid JSON, it contains invalid characters at the end of the output.
I had the same issue. First, look what is a data that wasn't parsed correctly - in my case I did
NSString *str = [[NSString alloc] initWithData:retrievedData encoding:NSUTF8StringEncoding];
In my case the reason was - if server sent a few socket.write()'s in a row - all data was received in one single chunk, like
{first:json}{second:json}..
of course this cannot be parsed as one single json, so I have to introduce delimiter, and split the received buffer into correct chunks.
This is a little late but nothing online worked for me until I did this:
NSString * dataInString = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
NSRange range = [dataInString rangeOfString:#"}" options:NSBackwardsSearch];
if(range.location != NSNotFound)
dataInString = [dataInString substringWithRange:NSMakeRange(0,range.location+1)];
Always worked since then.
I had the same error, the problem was my server was attaching some extra lines to my json response, that would not appear when i will get the response in my browser. Using curl from terminal you can see the actual output.
The hack was to truncate the extra characters. with json either you have an array or dictionary. Depending on your json structure, you can use the code (as above answer) but look for the comment in line 2
NSString * str = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
NSRange range = [str rangeOfString:#"}" options:NSBackwardsSearch]; // } for dictionary, ] for array
if(range.location != NSNotFound)
str = [str substringWithRange:NSMakeRange(0,range.location+1)];
once you get your string clean from garbage data, you can convert it to data again.
NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
and now from this data you can get your array or dictionary.
id jsonObject = [NSJSONSerialization
JSONObjectWithData:data
options:kNilOptions error:&error]; // i used id to be general, you can use array or dictionary structure or later cast this object to as per json

Resources