JSON декодирование эмоджи

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

JSON декодирование эмоджи

Сообщение Ichthyander » 10.11.2017 19:20:55

Декодирую строки из JSON представления с помощью JSONStringToString из модуля fpJSON. Все хорошо, кроме как если в тексте попадаются эмоджи (emoji).
К примеру, "/ud83c/udf1f/u0410/u043b/u043b..." должно декодироваться в "[ТУТ_КРАСИВЫЙ_ЭМОДЖИ_ДОЛЖЕН_БЫЛ_БЫТЬ]алле...", а на самом деле получаю "��лле...".
Кто что может посоветовать?
Кусок кода из модуля fpc fpJSON:
Код: Выделить всё
function JSONStringToString(const S: TJSONStringType): TJSONStringType;
Var
  I,J,L : Integer;
  P : PJSONCharType;
  w : String;

begin
  I:=1;
  J:=1;
  L:=Length(S);
  Result:='';
  P:=PJSONCharType(S);
  While (I<=L) do
    begin
    if (P^='') then
      begin
      Result:=Result+Copy(S,J,I-J);
      Inc(P);
      If (P^<>#0) then
        begin
        Inc(I);
        Case AnsiChar(P^) of
          '','"','/'
              : Result:=Result+P^;
          'b' : Result:=Result+#8;
          't' : Result:=Result+#9;
          'n' : Result:=Result+#10;
          'f' : Result:=Result+#12;
          'r' : Result:=Result+#13;
          'u' : begin
                W:=Copy(S,I+1,4);
                Inc(I,4);
                Inc(P,4);
                Result:=Result+WideChar(StrToInt('$'+W)); // Вот тут видимо "собака зарыта"?
                end;
        end;
        end;
      J:=I+1;
      end;
    Inc(I);
    Inc(P);
    end;
  Result:=Result+Copy(S,J,I-J+1);
end;


P.S. Кстати, поймал баг на форуме!
Если вставить эмоджи символ в пост на форуме, то вылетает ошибка MySQL:
Код: Выделить всё
[b]SQL ERROR [ mysql4 ]

Incorrect string value: 'xF0x9Fx8Cx9FxD0xA2...' for column 'post_text' at row 1 [1366]
[/b]

Причем, предварительный просмотр нормально работает, а вот при надажатии отправить, и, видимо, попытке сохранить в базу данных вылетает такая ошибка

Добавлено спустя 15 часов 29 минут 48 секунд:
Мои исследования функции JSONStringToString (fpJSON) привели меня к непонятным для меня результатам....
Код: Выделить всё
    procedure TForm1.Button3Click(Sender: TObject);
    var
      S, S1: TJSONStringType;
    begin
      S:='';
      S+=WideChar(StrToInt('$d83c'));
      S+=WideChar(StrToInt('$df1f'));
      S+=WideChar(StrToInt('$0410'));
      S1:='';
      S1+=WideChar(StrToInt('$d83c'))+WideChar(StrToInt('$df1f'))+WideChar(StrToInt('$0410'));
      EdtOutput.Text:='S: '+S+', S1: '+S1;
    end;

Вот это на выходе
2017-11-11_10-37-17.png

То есть конкантенация WideChar в одной строчке кода и последовательная конкантенация по строчке дают разные результате... Кто нибудь может объяснить?
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Последний раз редактировалось Ichthyander 11.11.2017 15:28:57, всего редактировалось 1 раз.
Аватара пользователя
Ichthyander
энтузиаст
 
Сообщения: 668
Зарегистрирован: 04.04.2007 08:32:43
Откуда: Астрахань

Re: JSON декодирование эмоджи

Сообщение Лекс Айрин » 11.11.2017 10:55:36

Ichthyander писал(а):Кто нибудь может объяснить?


Вероятно, некорректное неявное преобразование в utf8
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

Re: JSON декодирование эмоджи

Сообщение Ichthyander » 11.11.2017 14:29:35

Да, ошибка связанна именно с этим. Отписал баг-репорт.
Если у кого-то будет подобная же проблема, то она решается вот таким "хаком". Копируете функцию JSONStringToString в свой модуль.
Меняете тип результата функции с TJSONStringType на UnicodeString.
В итоге
Код: Выделить всё
function JSONStringToString(const S: TJSONStringType): UnicodeString;

Var
  I,J,L : Integer;
  P : PJSONCharType;
  w : String;

begin
  I:=1;
  J:=1;
  L:=Length(S);
  Result:='';
  P:=PJSONCharType(S);
  While (I<=L) do
    begin
    if (P^='\') then
      begin
      Result:=Result+Copy(S,J,I-J);
      Inc(P);
      If (P^<>#0) then
        begin
        Inc(I);
        Case AnsiChar(P^) of
          '\','"','/'
              : Result:=Result+P^;
          'b' : Result:=Result+#8;
          't' : Result:=Result+#9;
          'n' : Result:=Result+#10;
          'f' : Result:=Result+#12;
          'r' : Result:=Result+#13;
          'u' : begin
                W:=Copy(S,I+1,4);
                Inc(I,4);
                Inc(P,4);
                Result:=Result+WideChar(StrToInt('$'+W));
                end;
        end;
        end;
      J:=I+1;
      end;
    Inc(I);
    Inc(P);
    end;
  Result:=Result+Copy(S,J,I-J+1);
end;

Таким образом, эта функция отныне правильно декодирует в том числе и эмоджи в читабельный вид...
Аватара пользователя
Ichthyander
энтузиаст
 
Сообщения: 668
Зарегистрирован: 04.04.2007 08:32:43
Откуда: Астрахань


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 36

Рейтинг@Mail.ru