NSJSONСериализация и эмодзи

В настоящее время я пытаюсь отправить некоторый JSON, содержащий смайлики, в API Python. Я попытался передать NSJSONSerialization напрямую строку, содержащую смайлики, из моего UITextField, но сериализатор аварийно завершил работу без объяснения причин. После этого я попытался преобразовать формат и получил что-то вроде этого:

NSString *uniText = mytextField.text;
NSData *msgData = [uniText dataUsingEncoding:NSNonLossyASCIIStringEncoding];
NSString *goodMsg = [[NSString alloc] initWithData:msgData encoding:NSUTF8StringEncoding] ;

Это в основном работает, за исключением того, что полученный UTF-8 является своего рода двойным «экранированием», что приводит к следующему:

"title":"\\ud83d\\udc8f\\ud83d\\udc8f\\ud83d\\udc8f\\ud83d"

Любые предложения, как это исправить?


person Tim Specht    schedule 22.05.2014    source источник
comment
NSJSONSerialization должен работать.   -  person Martin R    schedule 22.05.2014
comment
Я думал, что это именно то, что должен был сделать NSNonLossyASCIIStringEncoding.   -  person Brad Allred    schedule 22.05.2014
comment
JSON ВСЕГДА должен быть UTF.   -  person Hot Licks    schedule 22.05.2014
comment
uniText содержит текст, который вы хотите. goodMsg содержит текст в каком-то испорченном формате. NSJSONSerialization отлично сериализовал бы uniText, вместо этого вы попросили его сериализовать ваш испорченный goodMsg.   -  person gnasher729    schedule 22.05.2014
comment
Нет. Я пытался ввести его напрямую, но он просто SIGABRT, исключение не печатается, точка останова исключения также ничего не делает ›.‹   -  person Tim Specht    schedule 22.05.2014
comment
Вы кодируете строку, используя одну кодировку, и пытаетесь декодировать результат, используя другую кодировку! Это, вероятно, не то, что вы хотели сделать.   -  person Ian Henry    schedule 22.05.2014
comment
Не используйте NSNonLossyASCIIStringEncoding, используйте NSUTF32LittleEndianStringEncoding. emoji находятся в UTF Plane 1 и, таким образом, представляют собой 21-битные кодовые точки.   -  person zaph    schedule 22.05.2014
comment
Я пытался использовать ваше предложение @Zaph, но я получаю нулевые данные :(   -  person Tim Specht    schedule 22.05.2014
comment
так что я могу сделать, чтобы решить проблему?   -  person Tim Specht    schedule 22.05.2014
comment
Посмотрите мой пример кода ответа, я не использовал ваши символы Юникода, можете ли вы публиковать, копировать и вставлять символы смайликов. Или в своем коде измените NSNonLossyASCIIStringEncoding на NSUTF32LittleEndianStringEncoding, запустите код и опубликуйте вывод.   -  person zaph    schedule 22.05.2014
comment
(NSString *) uniText = 0x1680e0a0 @????????????????????   -  person Tim Specht    schedule 22.05.2014
comment
Хорошо, спасибо за это. Если я копирую и вставляю ваш код, все работает нормально, только когда я пытаюсь использовать свое текстовое поле, все сходит с ума... есть идеи?   -  person Tim Specht    schedule 23.05.2014
comment
Запишите, что возвращается из текстового поля: NSLog(@"uniText utf-32: %@", [uniText dataUsingEncoding:NSUTF32LittleEndianStringEncoding]); и опубликуйте.   -  person zaph    schedule 23.05.2014


Ответы (2)


Есть две трудности:
1. Apple облила NSString WRT UTF Planes 1 и выше, но основное использование UTF-16 видно. Например, length вернет 2 для одного символа смайлика.
2. Кто бы ни решил поместить смайлик в уровень 1, ему просто было трудно, это первое использование уровня 1, и многие устаревшие коды UTF не справляются с этим. правильно.

Пример кода (адаптировано из @Hot Licks): обновлено смайликами OP.

NSString *uniText = @"????????????????????";
NSDictionary* jsonDict = @{@"title":uniText};

NSData * utf32Data = [uniText dataUsingEncoding:NSUTF32LittleEndianStringEncoding];
NSLog(@"utf32Data: %@", utf32Data);

NSError* error = nil;
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:jsonDict options:0 error:&error];
if (jsonData == nil) {
    NSLog(@"JSON serialization error: %@", error);
}
else {
    NSString* jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    NSLog(@"The JSON result is %@", jsonString);
    NSLog(@"jsonData: %@", jsonData);
}

Выход NSLog

utf32Data: a6f40100 8ff40100 52f40100 52f40100 a6f40100
The JSON result is {"title":"????????????????????"}
jsonData: 7b227469 746c6522 3a22f09f 92a6f09f 928ff09f 9192f09f 9192f09f 92a6227d

person zaph    schedule 22.05.2014

Вздох:

NSString* uniText = mytextField.text;
NSDictionary* jsonDict = @{@"title":uniText};
NSError* error = nil;
NSData* jsonData = [NSJSONSerialization dataWithJsonObject:jsonDict options:0 error:&error];
if (jsonData == nil) {
    NSLog(@"JSON serialization error: %@", error);
}
else {
    NSString* jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    NSLog(@"The JSON result is %@", jsonString);
}

Если myTextField.text является допустимым NSString, то никаких других преобразований не требуется. NSJSONSerialization обеспечит все необходимое «экранирование».

person Hot Licks    schedule 22.05.2014
comment
Я уже пробовал это. Я действительно просто скопировал ваш код, и строка, в которой происходит сериализация в NSData, просто вылетает из-за SIGABRT. Нет полезного исключения, установка точки останова исключений также не дает дальнейших результатов... - person Tim Specht; 22.05.2014
comment
Я исправил их, иначе я бы не смог скомпилировать это, очевидно ...NSString* text = metadata[@title]; NSDictionary* jsonDict = @{@title:text}; NSError* ошибка = ноль; NSData* jsonData = [NSJSONSerialization dataWithJSONObject: jsonDict options:0 error:&error]; if (jsonData == nil) { NSLog(@Ошибка сериализации @JSON: %@, ошибка); } else { NSString* jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; NSLog(@Результат JSON: %@, jsonString); } - person Tim Specht; 22.05.2014
comment
@TimSpecht Чем ответ Hot Licks отличается от ответа Zaph? - person Aaron Brager; 23.05.2014