Заметки · 05.04.2023

Парсим JSON в PowerShell

За всё время работы именно с PowerShell мне ещё ни разу не удавалось поработать с форматом JSON в этой среде, хотя неоднократно на глаза попадались командлеты ConvertTo-Json и ConvertFrom-Json. Решил провести эксперимент на простом примере свободного API какого-нибудь веб-проекта.

Есть такой интересный сайт (с гифками!) yesno.wtf. Каждый раз при обновлении сайт рандомно показывает анимированные мемы-ответы: да, нет и может быть (заявлено, что этот вариант появляется с вероятностью 1:10000). Так вот: к этому сайту прикручен прекрасный API с выводом на JSON!

Простой запрос (https://yesno.wtf/api/?force=yes) прямо из адресной строки браузера позволяет форсировать выпадающий вариант и получать ответ от сайта в виде ссылки на картинку.

Теперь подставляем запрос в командлет Invoke-WebRequest и получаем данные от сайта. После этого передаём результат командлету ConvertFrom-Json и получаем красоту.

Команда запроса:

Invoke-WebRequest -Uri https://yesno.wtf/api/?force=yes | ConvertFrom-Json

Вывод в консоль:

answer forced image                                                              
------ ------ -----                                                              
yes      True https://yesno.wtf/assets/yes/9-6403270cf95723ae4664274db51f1fd4.gif

Чтобы в качестве ответа получать только ссылку на изображение, нужно привести команду запроса к такому (примерно) виду:

(Invoke-WebRequest -Uri https://yesno.wtf/api/?force=yes | ConvertFrom-Json).image

Здесь я форсировал получение только изображений с ответом yes.

А теперь хотелось бы унифицировать запрос и сразу скачивать вожделенный gif (например) на рабочий стол. Так и появилась функция, которая в качестве аргумента принимает нужный ответ:

function GetImage ($answer)
{
    $getjson = Invoke-WebRequest -Uri https://yesno.wtf/api/?force=$answer
    $img = ($getjson.Content | ConvertFrom-Json).image
    $savepath = [Environment]::GetFolderPath("Desktop") + "\$answer.gif"
    $download = New-Object Net.WebClient
    $download.DownloadFile($img, $savepath)
}

Осталось добавить бесконечный цикл и переключалку. В конечном итоге получился скрипт для выбора варианта и скачивания полученного изображения:

function GetImage ($answer)
{
    $getjson = Invoke-WebRequest -Uri https://yesno.wtf/api/?force=$answer
    $img = ($getjson.Content | ConvertFrom-Json).image
    $savepath = [Environment]::GetFolderPath("Desktop") + "\$answer.gif"
    $download = New-Object Net.WebClient
    $download.DownloadFile($img, $savepath)
}

while($true)
{
    Write-Host
    Write-Host "1. Скачать yes.gif" -ForegroundColor Green
    Write-Host "2. Скачать no.gif" -ForegroundColor Red
    Write-Host "3. Скачать maybe.gif" -ForegroundColor Yellow
    Write-Host "4. Гадание" -ForegroundColor White
    Write-Host

    $choice = Read-Host "Что выберем?"

    switch($choice)
    {
        1{ GetImage("yes") }

        2{ GetImage("no") }

        3{ GetImage("maybe") }

        4{ 
           $ramdom = Get-Random -InputObject "yes", "no", "maybe"
           GetImage($ramdom)
         }

        default { Write-Host "Дичь какая-то..." -ForegroundColor Cyan }
    }
}

Теперь пользователь сам выбирает желаемый ответ, а функция скачивает гифку и размещает файл на рабочем столе. Чтобы немного сгладить упомянутую выше вероятность попадания на maybe — прикрутил к коду простейший рандомайзер на базе командлета Get-Random.

Можете тоже поиграться! Презабавнейшая штука!