При работе с HTTP-запросами в Delphi, особенно при взаимодействии с сервисами, использующими JSON, важно понимать, что JSON по умолчанию использует кодировку UTF-8. В Delphi 2010 и более новых версиях используется UTF-16 в качестве кодировки по умолчанию для строк. Это может привести к проблемам, если не выполнить необходимые преобразования перед отправкой JSON-объекта.
Проблема
Разработчик столкнулся с проблемой, когда отправляемый JSON-объект в Java-приложение был некорректно интерпретирован. При отладке с помощью снiffeра было обнаружено, что данные были искажены, что привело к возникновению исключения null pointer в Java-приложении.
Пример кода
В коде, предоставленном разработчиком, используется функция JSONPostRequest, которая выполняет HTTP-запрос с использованием API Wininet. Однако, проблема заключалась в том, что строка JSON, содержащая JSON-объект, не была преобразована в UTF-8 перед отправкой.
Решение
Для корректной работы с Java-приложением необходимо выполнить следующие шаги:
Преобразовать строку JSON из UTF-16 в UTF-8 перед отправкой запроса.
Добавить заголовок в запрос, указывающий, что данные отправляются в кодировке UTF-8.
Вот пример исправленной функции JSONPostRequest, которая учитывает эти требования:
function TFormMain.JSONPostRequest(const Server, Url: string; const jo : UTF8String; blnSSL: Boolean): String;
var
aBuffer : Array of Byte;
Header : String;
BufStream : TStringStream;
BytesRead : DWORD;
pSession : HINTERNET;
pConnection : HINTERNET;
pRequest : HINTERNET;
port : Integer;
flags : DWORD;
begin
// ... (инициализация, как в исходном коде)
end;
function WinInetErrorMsg(Err: DWORD): string;
var
ErrMsg: array of Char;
ErrLen: DWORD;
begin
// ... (реализация функции для получения сообщения об ошибке WinInet)
end;
begin
Result := '';
// ... (код инициализации сессии, соединения и запроса, как в исходном коде)
Header := 'Host: ' + Server + ':' + IntToStr(Port) + #13#10 +
'Content-Type: application/json; charset=UTF-8'#13#10;
// ... (проверка добавления заголовков запроса)
if not HTTPSendRequest(pRequest, nil, 0, PAnsiChar(jo), Length(jo)) then
raise Exception.Create('HTTPSendRequest failed. ' + WinInetErrorMsg(GetLastError));
// ... (код чтения ответа, как в исходном коде, с использованием TStringStream и TEncoding.UTF8)
Result := BufStream.DataString;
// ... (завершение работы с сессией и соединением)
end;
Важные замечания
Используйте UTF8String для параметра jo, чтобы указать, что строка уже в кодировке UTF-8.
Убедитесь, что JSON-строка не была подвергнута URL-encode перед отправкой.
Убедитесь, что флаг INTERNET_SERVICE_HTTP не используется в HTTPOpenRequest, так как это неверный флаг.
Заключение
При работе с HTTP-запросами в Delphi, особенно при использовании JSON, важно всегда проверять, что данные передаются в правильной кодировке. В данном случае, преобразование в UTF-8 и добавление соответствующего заголовка Content-Type позволит избежать некорректной интерпретации данных Java-приложением.
При разработке в Delphi 2010 для корректного взаимодействия Java-приложения с JSON-данными необходимо преобразовать строку JSON из UTF-16 в UTF-8 и добавить соответствующий заголовок Content-Type для указания кодировки данных.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS