2013-06-05 4 views
11

웹 서비스의 응답을 처리해야하는 iOS 앱이 있습니다. 이 응답은 JSON 문자열 아닌 JSON 객체임을NSJSONSerialization으로 어떻게 이스케이프 된 JSON 문자열을 비 직렬화 할 수 있습니까?

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

참고 : 응답은 다음과 같이 뭔가를 찾고, 직렬화 된 JSON 객체를 포함 직렬화 된 JSON 문자열입니다.

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

을 그리고 내가 NSDictionary에 그 역 직렬화하는 +[NSJSONSerialization JSONObjectWithData:options:error:]을 사용할 수 있습니다 : 내가 뭘해야 내가 이것을 얻을 수 있도록 문자열을 역 직렬화입니다.

하지만 첫 단계는 어떻게해야합니까? 즉, 문자열을 "이스케이프 (unescape)"하여 직렬화 된 JSON 객체를 얻는 방법은 무엇입니까? +[NSJSONSerialization JSONObjectWithData:options:error:]은 최상위 수준 개체가 배열 또는 사전 인 경우에만 작동합니다. 문자열에서는 작동하지 않습니다.

my own JSON string parser이 작성되었으므로 section 2.5 of RFC 4627을 준수하겠습니다. 그러나 나는 NSJSONSerialization 또는 다른 이용 가능한 방법을 사용하여 이것을하기위한 쉬운 방법을 간과 해 왔다고 생각합니다.

+0

는 그냥 선행 및 후행 quoteß을 차단하고 모든'\ "'의 교체 '''. –

+0

그런 다음 가능한 모든 이스케이프 시퀀스에 대해 이스케이프 처리 절차를 반복합니다 (매우 많음). –

+0

'\ uXXXX' 이스케이프 문자열은 검색과 바꾸기가 쉽지 않습니다. –

답변

24

당신이 중첩 된 경우 JSON을 두 번 JSONObjectWithData 전화 :

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

@KristopherJohnson : 나는이 코드를 정확하게 시험해 보았습니다. 첫 번째 단계에서는 NSJSONReadingAllowFragments 옵션이 필요합니다. –

+0

이전에'NSJSONReadingAllowFragments'를 시도했는데 작동하지 않았지만 지금은 맹세합니다. 다시 시도해 주셔서 감사합니다. –

0

데이터를 문자열로 변환 :

NSString *string = @"{ \"name\" : \"Bob\", \"age\" : 21 }"; 
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding]; 
NSError *error; 
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; 
+0

나는'NSData' 객체를 가지고 있는데, NSJSONSerialization'. 마치 코드가'string = @ "\"{\\ "name \\": \\ "Bob \\", \\ "age \\"처럼 : 21} \ "", " –

+0

어떻게 되는가? 너는 그 끈을 얻었 니? 파이프 라인을 따라 어딘가에 두 번 이스케이프 처리되는 것처럼 들리며 디버깅해야합니다. –

+1

웹 서비스가 이중 이스케이프 처리 중입니다. 당신과 나는 그것이 그렇게해서는 안된다는 것에 동의 할지도 모르지만, 나는 그것을 처리해야합니다. –

0

는 그냥 선행 및 후행 따옴표를 차단 한 후 "과의"모든 \ 대체 : 그냥 다음,

NSString *sub = [original substringWithRange:(NSRange){ 1, original.length - 2 }]; 
NSString *unescaped = [sub stringByReplacingOccurrencesOfString:@"\\\" withString:@"\"]; 
+0

그게 내 최초의 해킹 해결 방법 이었지만 문자열 ('\ n','\ t','\ u1234' 등)에 다른 특수 문자가없는 경우에만 작동합니다. 그러나 나는 그것을 추측 할 수 없다. –

+0

JSON 문자열은 이러한 문자를 이스케이프 처리해야합니다. 따라서 엔코더가 적용될 때 이스케이프가 이스케이프 처리됩니다. "(\\ n)" – CouchDeveloper

0

서버가 단지 포함하지 않는 이유 중 하나가 먼저 요청해야 JSON을 하위 구조로 사용합니다.

하지만 어쨌든. 당신이 가지고있는 문자열은 JSON으로 이스케이프 된 것 같습니다. 무엇 실제로는 의미, 완전히 웹 서비스 개발자에게 있습니다. 이중 따옴표와 이스케이프 자체는 도망 치다가 \으로 이스케이프되었습니다. 결과 문자열은 "serialize"되지 않습니다. JSON은 이미 serialize되어 있지만 으로 인코딩됩니다.

: -

조각 방법을 (그러나 이것은 너무 쉽게 당신이 목표 - C를 요청 알고)를 보여줍니다 ++ C 조금씩 : - 다시 복귀하기 위해서는 당신이 "언 이스케이프"또는 다시 디코딩 필요

편집 : 엔디안이있는 UTF-16 및 UTF-32에서도 코드가 작동해야합니다. 인코더가 기계적으로 의심 스러우면, 이스케이프 처리 된 유니 코드 문자 (예 : \ u1234 등

편집 - 아니요, UTF-16 및 UTF-32에서는 작동하지 않습니다. 견본은 그것을 위해 고쳐야 할 것입니다 (그것은 쉬울 것입니다). 그러나 UTF-8이 있는지 확인하십시오. 거의 항상 그렇습니다.

#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; 
} 

인쇄 :

{ "이름": "밥", "나이": 21}

+1

당신의 예제는 입력 된'{\ "name \": \ "Bob \", \ "age \": 21}'에서 작동합니다. 그러나 실제 서버 응답은 (이해할 수있는대로) "{\"name \ ": \"Bob \ ", \"age \ ": 21}"'(선행 및 후행 인용 부호에 유의하십시오). 그것이 NSJSONReadingAllowFragments가 작동하는 이유입니다. –

+0

OK, NSJSONSerialization은 이것을 JSON 문자열로 해석 한 다음이 최상위 객체 인 NSString을 반환합니다. 그래서 효과적으로 "JSON String decoder"를 주어진 문자열에 적용합니다. 그게 효과가 있을지 모르지만, 어쨌든 주어진 문자열이 웹 서비스에 의해 어떻게 해독되었는지 분명히 할 것이다. – CouchDeveloper