Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Delphi и кодировка UTF8 для JSON

8
12 мая 2013 года
mfender
3.5K / / 15.06.2005
Какое нужно сделать чудо, чтобы Delphi2010 делал мне нормальный JSON?
Делаю как-то так:
 
Код:
AddPair('MsgText', TJSONString.Create(MsgText));
В результате в JSON'е получается {"MsgText":"Какой-то текст русскими буквами"}, только с совершенно ASCII кодировкой, что противоречит насмерть идеям JSON.
Привыкши извращаться в Delphi7 с TlkJSON, где символы перекодируются сразу и корректно, сейчас не могу врубиться, в какую сторону искать в этом направлении в D2010. Задницей чую, что есть какие-то конвертеры в Delphi, но в ней такой дебиловатый мануал, что вообще ничего не описывается и ничего в нём существенного нет.

Собственно вопрос: как преобразовывать в Delphi2010 ASCII в UTF8/Unicode?
1
12 мая 2013 года
kot_
7.3K / / 20.01.2000
К сожалению нет под рукой данного поделия что бы проверить - но в билдере тех же версий различие заключалосьв использовании классов String / AnsiString - соотвественно для ютф - надо было использовать String. Ну и можно задать кодировку которая будет использоваться.
8
12 мая 2013 года
mfender
3.5K / / 15.06.2005
Ну вот я сейчас чуток Кэнту покурил. Он утверждает, что в Delphi 2009 и дальше string = UnicodeString. Соответственно и в DBXJSON:
 
Код:
constructor TJSONString.Create(const Value: UnicodeString);
Вроде всё правильно, но так как я в конструктор отдаю AnsiString ('Буквы русского алфавита'), они так и остаются однобайтными символами. Уже всяко крутил-вертел, и в Hexeditor'е всякий раз сверялся.

И самое главное, никак не получается получить вот это, что делает JavaScript и PHP:
 
Код:
{"field1":"\u0411\u0443\u043a\u0432\u044b \u043f\u043e\u043b\u044f field1","field2":"\u0411\u0443\u043a\u0432\u044b \u043f\u043e\u043b\u044f field2"}
1
12 мая 2013 года
kot_
7.3K / / 20.01.2000
Ну так может не надо отдавать AnsiString? :)
8
12 мая 2013 года
mfender
3.5K / / 15.06.2005
Вот я и спрашиваю: что нужно сделать, чтобы строка UnicodeString, в которой я пишу русские буквы, содержала Unicode, и в нужном виде попадала в JSON, чтобы этот JSON был правильный, а не то что я сейчас получаю, и что понимает только Delphi, да и то в виде кракозяблов. А если этот JSON отдать на съедению json_decode() в PHP - он вообще игнорирует его, потому что неправильный он.
7
12 мая 2013 года
@pixo $oft
3.4K / / 20.09.2006
Я так понимаю, здесь действует такое же различие, как и в C++ между "" и L"". Как в Delphi такой эффект достигается?
1
12 мая 2013 года
kot_
7.3K / / 20.01.2000
Цитата: mfender
Вот я и спрашиваю: что нужно сделать, чтобы строка UnicodeString, в которой я пишу русские буквы, содержала Unicode, и в нужном виде попадала в JSON, чтобы этот JSON был правильный, а не то что я сейчас получаю, и что понимает только Delphi, да и то в виде кракозяблов. А если этот JSON отдать на съедению json_decode() в PHP - он вообще игнорирует его, потому что неправильный он.


Так еще раз говорю - не надо AnsiString - надо String отдавать. В версиях выше 7 это разные типы.

8
12 мая 2013 года
mfender
3.5K / / 15.06.2005
Цитата: kot_

Так еще раз говорю - не надо AnsiString - надо String отдавать. В версиях выше 7 это разные типы.


Вот я пишу код:

Код:
type
  TmfAgregatorOneLogMessage = class(TmfLogMessage)
    property MsgText: String read FMsgText write FMsgText;
  public
    property JSON: TJSONObject read GetJSON write SetJSON;
  end;     

function TmfAgregatorOneLogMessage.GetJSON: TJSONObject;
begin
  Result := TJSONObject.Create;
  try
    with Result do
    begin
    .............
      AddPair('MsgText', TJSONString.Create(MsgText));
    end;
  finally
  end;
end;

{И где-то там ещё...}
........
var
  Mess: TmfAgregatorOneLogMessage;
  JS: UnicodeString;
.........
// Создаётся объект со строкой, которая написана вот тут в коде русскими буквами
// которое попадает в JSON в виде Ansi строки, а не Unicode как хочется
  Mess := LError(Self, 'Сообщение русскими буквами');
  JS := Mess.JSON.ToString;
8
12 мая 2013 года
mfender
3.5K / / 15.06.2005
Вобщем, у меня потекли мозги. И не от жары. От этого новомодного Delphi.
 
Код:
var MessStr: string;

  MessStr := UTF8Encode('Строка русскими буквами');
  showmessage(IntToStr(StringCodePage(UTF8Encode('Строка русскими буквами'))));
  showmessage(IntToStr(StringCodePage(MessStr)));
Первый алерт пишет 65001, второй - 1200.
Что же смерть не идёт, Захария?
10
19 мая 2013 года
Freeman
3.2K / / 06.03.2004
Не пользуюсь регулярно модным Delphi, но из того, что знаю, нужно делать примерно так:

 
Код:
var
  S: UTF8String;
begin
  S := 'Строка русскими буквами';
  ...
  AddPair('MsgText', TJSONString.Create(S));
end;
Думается, допустим и более короткий вариант:

 
Код:
begin
  ...
  AddPair('MsgText', TJSONString.Create(UTF8String('Строка русскими буквами')));
end;
Если идеология поддержки строк компилятором осталась прежней, невинное на первый взгляд приведение типа на нижнем уровне должно вызывать библиотечную функцию, выполняющую реальное перекодирование.
465
19 мая 2013 года
QWERYTY
595 / / 25.03.2012
Цитата: mfender
Вобщем, у меня потекли мозги. И не от жары. От этого новомодного Delphi.
 
Код:
var MessStr: string;

  MessStr := UTF8Encode('Строка русскими буквами');
  showmessage(IntToStr(StringCodePage(UTF8Encode('Строка русскими буквами'))));
  showmessage(IntToStr(StringCodePage(MessStr)));
Первый алерт пишет 65001, второй - 1200.
Что же смерть не идёт, Захария?



Проблема решилась? Если да то объясните в кратце что служило источником проблемы и метод её устранения.

Я просто честно не понимаю от чего текут мозги. Вы объявили переменную типа UnicodeString(тот же string), потом вы переменной присваиваете результат функции UTF8Encode.

Но!!!

Результат функции UTF8Encode имеет тип RawByteString и не совпадает с типом переменной. Компилятор видит что допущена ошибка, но не начинает еб*ть бошку как с++, а просто исправляет её и сообщает об этом вот таким сообщением:
[DCC Warning] Unit1.pas(30): W1057 Implicit string cast from 'RawByteString' to 'string'


И в алертах всё верно.
В первом как вы и хотели преобразовано в RawByteString с кодовой страницей 65001(UTF-8)
Во втором после вашей конвертации студия для записи в переменную конвертит в юникод. А про юникод я гдето читал примерно следующее:
Переменные UnicodeString всегда помечены кодировкой 1200, при любом типе инициализации и присвоения.

465
20 мая 2013 года
QWERYTY
595 / / 25.03.2012
Цитата: mfender
...
а не то что я сейчас получаю, и что понимает только Delphi, да и то в виде кракозяблов.
...



Кстати если делфи после себя не может считать строку и выводит так называемые кракозяблы то должны были быть сообщения о неявном преобразовании типов(наподобии как в посте выше, но там указывается что возможна потеря данных) . Реагировать на это или нет решать программисту.

Freeman уже подсказал конструкцию которая должна работать.
Вы наверное видели в моих вопросах вот такие вещи:

 
Код:
переменная := GetProcAddress(Mwwin32Handle, PAnsiChar('Имя Функции'));
Я явно указывал что это указатель на начало анси строки и компилятор без всяких сообщений переводил её из своего string(по умолчанию) в AnsiString.


Когда я переходил с D7 на D2010 это было настоящим убийством мозга. Но потом(с практикой) понимание приходит.
8
21 мая 2013 года
mfender
3.5K / / 15.06.2005
Вот у меня тоже с переходом с D7 на D2010 произошло это самое убийство мозга. Хорошо хоть не купил её сразу. А то бы волосы на ягодицах рвал.
Проблема решилась удивительно просто: всё это сделал на XE2. Там не случилось этих кодировочных troubles в JSON. Я пока не смог понять как у них так это получается. Наверное совсем не гуру. Но буду думать об этом, может понимание придёт к старости.

Знаете кого-то, кто может ответить? Поделитесь с ним ссылкой.

Ваш ответ

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог