Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 07.11.2020, 12:38   #1
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию И снова JSON

Здравствуйте.
Имеем код который скачивает кучу JSON-файлов и склеивает их в один большой JSON:
Код:
function TForm1.GetChannelVideosListJSON(aChannelName: string; MaxVids : Integer;
                                         var ResList: string) : Integer;
var
  json, json2, JsonToSave : TJSONObject;
  jp : TJSONPair;
  jsonArr, jsa : TJSONArray;
  total, offset, sum, max, i, ErrorCode : Integer;
  buf : AnsiString;
  t : string;
  ui : TTwitchUserInfoStruct;
begin
  Result := 0;
  if aChannelName = '' then
  Exit;
  if GetUserInfo(aChannelName, ui) then
  begin
    total := 0;
    sum := 0;
    offset := 0;
    JsonToSave := TJSONObject.Create;
    jsa := TJSONArray.Create;
    jp := TJSONPair.Create('videos', jsa);
    repeat
      t := 'https://api.twitch.tv/kraken/channels/' + ui.ID +
            '/videos?broadcast_type=all&limit=100&offset=' + IntToStr(offset);
      ErrorCode := Https_Get(t, buf);
      if ErrorCode = 200 then
      begin
        json := TJSONObject.ParseJSONValue(UTF8ToString(buf)) as TJSONObject;
        if total = 0 then
        begin
          total := StrToInt(json.Get('_total').JsonValue.Value);
          if MaxVids > 0 then
          begin
            if MaxVids >= total then
            max := total else
            max := MaxVids;
          end else
          max := total;
          Result := max;
        end;
        if total > 0 then
        begin
          jsonArr := json.Get('videos').JsonValue as TJSONArray;
          for I := 0 to jsonArr.Count - 1 do
          begin
            lbLog.Items.Delete(lbLog.Items.Count - 1);
            lbLog.Items.Add('Скачивание списка стримов канала ' + aChannelName + '... ' +
              IntToStr(sum + 1) + ' / ' + IntToStr(max));
            t := (JsonArr.Get(i) as TJSONObject).Get('url').JsonValue.Value;
            t := ExtractVideoIDFromURL(t);
            if (t <> '') and (Https_Get(StringReplace(TWITCH_VIDEO_INFO_URL,
                     '<video_id>', t, [rfReplaceAll]), buf) = 200) then
            begin
              json2 := TJSONObject.ParseJSONValue(UTF8ToString(buf)) as TJSONObject;
              jsa.AddElement(json2);
            end;
            inc(sum);
            if sum >= max then
            Break;
            Application.ProcessMessages;
          end;
        end else
        begin
          json.Free;
          Break;
        end;
        json.Free;
      end;
      offset := offset + 100;
      Application.ProcessMessages;
    until (sum >= max) or (ErrorCode <> 200);
    JsonToSave.AddPair(jp);
    if Result > 0 then
    ResList := JsonToSave.ToJSON;
    JsonToSave.Free;
  end;
end;
Процедура сохранения этого файла:
Код:
procedure SaveStringToFile(t, fn : string);
const
  bom : Word = $FEFF;
var
  hf : HFILE;
  by : Cardinal;
begin
  if FileExists(fn) then
  DeleteFile(fn);
  hf := CreateFile(PChar(fn), GENERIC_WRITE, 0,0,
            CREATE_NEW, FILE_ATTRIBUTE_NORMAL,  0);
  if hf <> INVALID_HANDLE_VALUE then
  begin
    WriteFile(hf, bom, 2, by, nil);
    WriteFile(hf, t[1], length(t) * 2, by, nil);
    CloseHandle(hf);
  end;
end;
В результате получается такой файл: https://cloud.mail.ru/public/3QFA/38R4WnLUX
Он нормально читается в проекте, в котором был создан. Но его необходимо прочитать и распарсить в другом проекте. Вот тут-то и начинаются проблемы.
Не правильно читается блок
Код:

            "preview": {
                "small": "https:\/\/static-cdn.jtvnw.net\/cf_vods\/d2nvs31859zcd8\/e7068fa4b63a378dd4e5_modestal_366026002_1486943636\/\/thumb\/thumb0-80x45.jpg",
                "medium": "https:\/\/static-cdn.jtvnw.net\/cf_vods\/d2nvs31859zcd8\/e7068fa4b63a378dd4e5_modestal_366026002_1486943636\/\/thumb\/thumb0-320x180.jpg",
                "large": "https:\/\/static-cdn.jtvnw.net\/cf_vods\/d2nvs31859zcd8\/e7068fa4b63a378dd4e5_modestal_366026002_1486943636\/\/thumb\/thumb0-640x360.jpg",
                "template": "https:\/\/static-cdn.jtvnw.net\/cf_vods\/d2nvs31859zcd8\/e7068fa4b63a378dd4e5_modestal_366026002_1486943636\/\/thumb\/thumb0-{width}x{height}.jpg"
            }
В прочитанной строке получается два слеша вместо одного.
Код:
1486943636//thumb
Как прочитать, чтобы был один слеш?
Там в оригинале только один слеш. А при добавлении в массив их становится два. Откуда второй берётся? И почему только в полях этого блока? Почему раздваиваются не все слеши, а только перед словом "thumb"?
BLACK_RAIN вне форума Ответить с цитированием
Старый 09.11.2020, 12:48   #2
tarakan1983
Форумчанин
 
Аватар для tarakan1983
 
Регистрация: 09.09.2008
Сообщений: 418
По умолчанию

А почему перед сохранением JSON не использовать stringreplace ???
tarakan1983 вне форума Ответить с цитированием
Старый 09.11.2020, 13:28   #3
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию

Цитата:
Сообщение от tarakan1983 Посмотреть сообщение
stringreplace
что на что реплейсить?
BLACK_RAIN вне форума Ответить с цитированием
Старый 09.11.2020, 13:38   #4
tarakan1983
Форумчанин
 
Аватар для tarakan1983
 
Регистрация: 09.09.2008
Сообщений: 418
По умолчанию

я так понял
Код:
\/\/
на
Код:
//
.
Может я не понял суть задачи?
Или если конкретно в месте с thumb, то
Код:
\/\/thumb\/
на
Код:
\/thumb\/

Последний раз редактировалось tarakan1983; 09.11.2020 в 13:40.
tarakan1983 вне форума Ответить с цитированием
Старый 09.11.2020, 14:20   #5
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию

Так можно случайно заменить данные там, где не надо.
И StringReplace не работает с длинными строчками. Проверял на каком-то JSON'е. Он ломался.
BLACK_RAIN вне форума Ответить с цитированием
Старый 09.11.2020, 14:29   #6
tarakan1983
Форумчанин
 
Аватар для tarakan1983
 
Регистрация: 09.09.2008
Сообщений: 418
По умолчанию

Тогда нужно 2-3 json источника, попробовать запустить Ваш код и посмотреть, что получиться в итоге. А так угадать почему в этом месте получаются 2 слеша я не умею.
tarakan1983 вне форума Ответить с цитированием
Старый 09.11.2020, 15:02   #7
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию

Цитата:
Сообщение от tarakan1983 Посмотреть сообщение
Тогда нужно 2-3 json источника, попробовать запустить Ваш код и посмотреть
Передайте в мою функцию названия каналов с твича. Например, miramisu, frozzyaka, modestal.
Понадобится дополнительный код:
Код:
const
  TWITCH_V5_ACCEPT : string = 'application/vnd.twitchtv.v5+json';
  TWITCH_CLIENT_ID : string = 'kimne78kx3ncx6brgo4mv6wki5h1ko';

type
  TTwitchUserInfoStruct = record
    DisplayName : string;
    Name : string;
    ID : string;
    Bio : string;
    UserType : string;
    CreationDate : TDateTime;
    LastUpdateDate : TDateTime;
    LogoURL : string;
  end;

function JsonDateToDateTime(JsonDate : string): TDateTime;
var
  t : string;
  st : TSystemTime;
begin
  t := Copy(JsonDate, 1,4);
  st.wYear := StrToInt(t);
  t := Copy(JsonDate, 6, 2);
  st.wMonth := StrToInt(t);
  t := Copy(JsonDate, 9, 2);
  st.wDay := StrToInt(t);
  t := Copy(JsonDate, 12, 2);
  st.wHour := StrToInt(t);
  t := Copy(JsonDate, 15, 2);
  st.wMinute := StrToInt(t);
  t := Copy(JsonDate, 18, 2);
  st.wSecond := StrToInt(t);
  st.wMilliseconds := 0;

  Result := SystemTimeToDateTime(st);
end;

function GetUserInfo(ChannelName : string;
                     var UserInfo : TTwitchUserInfoStruct) : Boolean;
var
  Json : TJSONObject;
  jsonArr : TJSONArray;
  t : string;
  buf : AnsiString;
begin
  UserInfo.Name := ChannelName;
  if Https_Get(StringReplace(TWITCH_USER_LOGIN_URL, '<channame>',
                        ChannelName, [rfReplaceAll]), buf) = 200 then
  begin
    t := UTF8ToString(buf);
    Json := TJSONObject.ParseJSONValue(t) as TJSONObject;
    jsonArr := json.Get('users').JsonValue as TJSONArray;
    if (Assigned(jsonArr)) and (jsonArr.Count > 0) then
    begin
      t := (jsonArr.Get(0) as TJSONObject).Get('created_at').JsonValue.Value;
      UserInfo.CreationDate := JsonDateToDateTime(t);
      t := (jsonArr.Get(0) as TJSONObject).Get('updated_at').JsonValue.Value;
      UserInfo.LastUpdateDate := JsonDateToDateTime(t);
      UserInfo.DisplayName := (jsonArr.Get(0) as TJSONObject).Get('display_name').JsonValue.Value;
      UserInfo.ID := (jsonArr.Get(0) as TJSONObject).Get('_id').JsonValue.Value;
      UserInfo.Bio := (jsonArr.Get(0) as TJSONObject).Get('bio').JsonValue.Value;
      UserInfo.UserType := (jsonArr.Get(0) as TJSONObject).Get('type').JsonValue.Value;
      UserInfo.LogoURL := (jsonArr.Get(0) as TJSONObject).Get('logo').JsonValue.Value;
      Result := True;
    end else
    Result := False;
    json.free;
  end else
  Result := False;
end;

function Https_Get(sURL : string; var RecvText : AnsiString) : Integer;
const
  sUserAgent = 'Mozilla/5.001 (windows; U; NT4.0; en-US; rv:1.0) Gecko/25250101';
var
  hInet, hConnect, hRequest : HINTERNET;
  lpdwBufferLength: DWORD;
  lpdwReserved    : DWORD;
  dwBytesRead     : DWORD;
  lpdwNumberOfBytesAvailable : DWORD;
  _pos : Cardinal;
  ServerName, Resource, Header : string;
  ResponseText : AnsiString;
  p : PChar;
begin
  Result := -1;
  _pos := Pos('://', sURL);
  Header := Copy(sURL, 1, _pos + 2);
  Delete(sURL, 1, _pos + 2);
  _pos := Pos('/', sURL);
  ServerName := Copy(sURL, 1, _pos - 1);
  Delete(sURL, 1, _pos - 1);
  Resource := sURL;
  hInet := InternetOpen(PChar(sUserAgent), INTERNET_OPEN_TYPE_PRECONFIG,
                        nil, nil, 0);
  if Assigned(hInet) then
  begin
    hConnect := InternetConnect(hInet, PChar(ServerName),
                  INTERNET_DEFAULT_HTTPS_PORT, nil, nil,
                  INTERNET_SERVICE_HTTP, 0, 0);
    if Assigned(hConnect) then
    begin
      p := PChar('Accept: ' + TWITCH_V5_ACCEPT + #0);
      hRequest := HttpOpenRequest(hConnect, 'GET', PChar(Resource),
                  HTTP_VERSION, '', @p, INTERNET_FLAG_SECURE, 0);
      if Assigned(hRequest) then
      begin
        Header := 'Client-ID: ' + TWITCH_CLIENT_ID;
        if not HttpSendRequest(hRequest, PChar(Header), Length(Header), nil, 0) then
        begin
          InternetCloseHandle(hRequest);
          InternetCloseHandle(hConnect);
          InternetCloseHandle(hInet);
          Exit;
        end;

        lpdwBufferLength := SizeOf(dword);
        lpdwReserved := 0;
        if not HttpQueryInfo(hRequest,
                             HTTP_QUERY_STATUS_CODE or HTTP_QUERY_FLAG_NUMBER,
                             @result, lpdwBufferLength, lpdwReserved) then
        begin
          InternetCloseHandle(hRequest);
          InternetCloseHandle(hConnect);
          InternetCloseHandle(hInet);
          Exit;
        end;

        if Result = 200 then
        begin
          _Pos := 1;
          ResponseText := '';
          repeat
            if not InternetQueryDataAvailable(hRequest,
                                lpdwNumberOfBytesAvailable, 0, 0) then
            begin
              InternetCloseHandle(hRequest);
              InternetCloseHandle(hConnect);
              InternetCloseHandle(hInet);
              Exit;
            end;
            SetLength(ResponseText, Length(ResponseText) +
                           Integer(lpdwNumberOfBytesAvailable));
            InternetReadFile(hRequest, @ResponseText[_pos],
                            lpdwNumberOfBytesAvailable, dwBytesRead);
            Inc(_Pos, dwBytesRead);
          until dwBytesRead = 0;
          RecvText := ResponseText;
        end;
        InternetCloseHandle(hRequest);
      end;
      InternetCloseHandle(hConnect);
    end;
    InternetCloseHandle(hInet);
  end;
end;
вроде ничего не забыл

Последний раз редактировалось BLACK_RAIN; 09.11.2020 в 15:11.
BLACK_RAIN вне форума Ответить с цитированием
Старый 09.11.2020, 15:20   #8
tarakan1983
Форумчанин
 
Аватар для tarakan1983
 
Регистрация: 09.09.2008
Сообщений: 418
По умолчанию

Цитата:
Сообщение от BLACK_RAIN Посмотреть сообщение
вроде ничего не забыл
TWITCH_USER_LOGIN_URL
tarakan1983 вне форума Ответить с цитированием
Старый 09.11.2020, 15:27   #9
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию

Цитата:
Сообщение от tarakan1983 Посмотреть сообщение
TWITCH_USER_LOGIN_URL
TWITCH_USER_LOGIN_URL = 'https://api.twitch.tv/kraken/users?login=<channame>';
BLACK_RAIN вне форума Ответить с цитированием
Старый 09.11.2020, 15:34   #10
tarakan1983
Форумчанин
 
Аватар для tarakan1983
 
Регистрация: 09.09.2008
Сообщений: 418
По умолчанию

Цитата:
Сообщение от BLACK_RAIN Посмотреть сообщение
вроде ничего не забыл
Код:
t := ExtractVideoIDFromURL(t);
tarakan1983 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
JSON PTyTb32 Общие вопросы Delphi 0 02.06.2018 10:44
Работа с JSON (System.JSON) nibufep Общие вопросы Delphi 3 19.04.2016 18:21
JSON Exception [org.apache.json] spectrum988 Помощь студентам 3 11.12.2015 09:25
Снова я и снова геморрой, только уже с многопоточностью FleXik Общие вопросы Delphi 26 07.07.2013 16:48
MDIChild снова и снова... Siber_Dec Общие вопросы Delphi 2 13.12.2009 03:24