1

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.

prettyvoid
  • 3,446
  • 6
  • 36
  • 60
  • You are obviously transmitting the JSON data using a technique that corrupts data it doesn't like. This is not a problem with JSON, but either you've picked the wrong protocol or you're not somehow escaping the data as you should, given the protocol you picked. – Hot Licks Nov 10 '14 at 19:51
  • @Daij-Djan - Reading as ASCII would not cause problems with `&`. – Hot Licks Nov 10 '14 at 20:12
  • Then my question is maybe how to properly encode the HTTPBody? To be more specific, how can the i 'html escape' the HTTPBody? For example on my android app, when I convert the dictionary to json, I get `\uc0026` instead of the ampersand and when I send the data to my server, i receive the full payload and my server is happy. @HotLicks , my request is done via normal NSUrlRequest and the web service is a .NET asmx web service – prettyvoid Nov 10 '14 at 20:26
  • 1
    I was obviously wrong with my thought of character encoding. hot licks knew the answer for hours, maybe he'll post it now – Daij-Djan Nov 10 '14 at 22:35
  • 1
    The best approach is to use a protocol that treats the JSON as pure binary. This is a function of the types you assign in the HTTP request, and using, IIRC, POST vs PUT. – Hot Licks Nov 10 '14 at 22:36
  • So I take it from your comment that the current protocol is treating the json as text, that's why it should be encoded in a specific format. Can you pretty please explain the fundamentals of this (in a separate answer maybe)? I'm really new to the whole web development thing and I would appreciate it if someone explains why I'm facing such a problem and how to cure it. Thanks a lot – prettyvoid Nov 10 '14 at 22:41
  • Could it be related to data in the header such as application/x-www-form-urlencoded? – prettyvoid Nov 10 '14 at 22:47

1 Answers1

0

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.

Community
  • 1
  • 1
kk1
  • 53
  • 4