How can you deserialize an escaped JSON string with NSJSONSerialization?

后端 未结 4 1171
名媛妹妹
名媛妹妹 2020-12-03 05:21

I have an iOS app that needs to process a response from a web service. The response is a serialized JSON string containing a serialized JSON object, looking something like t

相关标签:
4条回答
  • 2020-12-03 06:01

    Convert the string to data:

    NSString *string = @"{ \"name\" : \"Bob\", \"age\" : 21 }";
    NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
    NSError *error;
    id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
    
    0 讨论(0)
  • 2020-12-03 06:07

    Just cut off the leading and trailing quotes and then replace all \"s with ":

    NSString *sub = [original substringWithRange:(NSRange){ 1, original.length - 2 }];
    NSString *unescaped = [sub stringByReplacingOccurrencesOfString:@"\\\" withString:@"\"];
    
    0 讨论(0)
  • 2020-12-03 06:23

    If you have nested JSON, then just call JSONObjectWithData twice:

    NSString *string =  @"\"{ \\\"name\\\" : \\\"Bob\\\", \\\"age\\\" : 21 }\"";
    // --> the string
    // "{ \"name\" : \"Bob\", \"age\" : 21 }"
    
    NSError *error;
    NSString *outerJson = [NSJSONSerialization JSONObjectWithData:[string dataUsingEncoding:NSUTF8StringEncoding]
                                  options:NSJSONReadingAllowFragments error:&error];
    // --> the string
    //  { "name" : "Bob", "age" : 21 }
    NSDictionary *innerJson = [NSJSONSerialization JSONObjectWithData:[outerJson dataUsingEncoding:NSUTF8StringEncoding]
                                  options:0 error:&error];
    // --> the dictionary
    // { age = 21; name = Bob; }
    
    0 讨论(0)
  • 2020-12-03 06:24

    One should first ask, why the server just don't include the JSON, as a sub structure.

    But anyway. The string you got seems to be an escaped JSON. What that actually means, is totally up to the web service developer. I suspect, that just the double quotes and an escape itself have been escaped with an escape \. The resulting string is not "serialized" - JSON is already serialized - but encoded. In order to revert it back - you need to "unescape" or decode it again:

    A little C++ snippet shows how (I know you asked for Objective-C -- but this is just too easy):

    Edit: the code should also work for UTF-16 and UTF-32 -- with any endianness - and if the encoder just mechanically did what I suspect, it should also work for escaped unicode characters, e.g. \u1234 etc.

    Edit - no, it won't work for UTF-16 and UTF-32. The sample would have to be fixed for that (which would be easy). But please ensure you have UTF-8 - which is almost always the case.

    #include <iostream>
    
    char input[] = u8R"___({ \"name\" : \"Bob\", \"age\" : 21 })___";
    
    // Unescapes the character sequence "in-situ".
    // Returns a pointer to "past-the-end" of the unescaped string.
    static char* unescape(char* first, char* last) {
        char* dest = first;
        while (first != last) {
            if (*first == '\\') {
                ++first;
            }
            *dest++ = *first++;
        }
        return dest;
    }
    
    int main(int argc, const char * argv[])
    {
        char* first = input;
        char* last = first + strlen(input);
        std::string s(input, unescape(first, last));
    
        std::cout << s << std::endl;
    
        return 0;
    }
    

    Prints:

    { "name" : "Bob", "age" : 21 }

    0 讨论(0)
提交回复
热议问题