Тема: AHK: Преобразовать строку JSON в объект
Пост-задача, по типу прежнего "Прошу подключиться к решению загадки", но только для AHK, поэтому пишу здесь.
Вначале о том, что такое JSON, для тех, кто не знает:
JSON строится на двух структурах:
Набор пар ключ/значение. В различных языках это реализовано как объект, запись, структура, словарь, хэш-таблица, список с ключом или ассоциативный массив. Ключом может быть только строка, значением — любая форма.
Пронумерованный набор значений. Во многих языках это реализовано как массив, вектор, список или последовательность.
... ... ...
В JSON используются их следующие формы:Объект — это неупорядоченное множество пар имя/значение, заключённое в фигурные скобки { }. Между именем и значением стоит символ ": ", а пары имя/значение разделяются запятыми.
Массив (одномерный) — это множество значений, имеющих порядковые номера (индексы). Массив заключается в квадратные скобки [ ]. Значения отделяются запятыми.
Значение может быть строкой в двойных кавычках, числом, значением true или false, объектом, массивом, или значением null. Эти структуры могут быть вложены друг в друга.
Строка — это упорядоченное множество из нуля или более символов юникода, заключенное в двойные кавычки, с использованием escape-последовательностей начинающихся с обратной косой черты (backslash). Символы представляются простой строкой.
Имя — это строка.Строка очень похожа на строку в языках С и Java. Число тоже очень похоже на С или Java-число, за исключением того, что используется только десятичный формат. Пробелы могут быть вставлены между любыми двумя символами.
Следующий пример показывает JSON-представление объекта, описывающего человека. В объекте есть строковые поля имени и фамилии, объект, описывающий адрес, и массив, содержащий список телефонов.
{
"firstName": "Иван",
"lastName": "Иванов",
"address": {
"streetAddress": "Московское ш., 101, кв.101",
"city": "Ленинград",
"postalCode": 101101
},
"phoneNumbers": [
"812 123-1234",
"916 123-4567"
]
}
Именно в формате JSON приходит ответ от Google при работе скрипта из темы "Онлайн переводчик". Приходит, естественно, не в виде объекта, а в виде строки. Пример:
from := "ru"
to := "en"
Sourse := "ответ"
Url := "http://translate.google.com/translate_a/t?client=x&sl=" . from . "&tl=" . to . "&text=" URIEncode(Sourse)
Answer := UrlDownloadToVar(Url, "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)")
Run, notepad.exe,,, PID
WinWait, ahk_class Notepad ahk_pid %PID%
ControlSetText, Edit1, %Answer%
return
URIEncode(Str)
{
b_Format:=A_FormatInteger
SetFormat, Integer, Hex
Loop, % StrPutVar(Str, Var, "UTF-8")
{
Ch:=NumGet(Var, A_Index-1, "UChar")
If Ch=0
Break
If (Ch>0x7f Or Ch<0x30 Or Ch=0x3d)
s.="%"((StrLen(c:=SubStr(Ch, 3))<2) ? "0"c:c)
Else
s.=Chr(Ch)
}
SetFormat, Integer, % b_Format
Return, s
}
StrPutVar(string, ByRef var, encoding = "CP0")
{
; Ensure capacity.
VarSetCapacity( var, StrPut(string, encoding)
; StrPut returns char count, but VarSetCapacity needs bytes.
* ((encoding="utf-16"||encoding="cp1200") ? 2 : 1) )
; Copy or convert the string.
return StrPut(string, &var, encoding)
}
UrlDownloadToVar(URL, UserAgent = "")
{
WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1")
WebRequest.Open("GET", Url)
WebRequest.Option(WinHttpRequestOption_UserAgentString := 0) := UserAgent
WebRequest.Send()
Text := WebRequest.ResponseText
WebRequest := ""
return Text
}
В результате выполнения вышеприведённого скрипта появляется окно блокнота с текстом, который присылает Google в ответ на запрос перевести слово "ответ" с русского на английский.
Должно придти следующее:
{"sentences":[{"trans":"answer","orig":"ответ","translit":"","src_translit":"otvet"}],"dict":[{"pos":"noun","terms":["response","answer","reply","return","rejoinder","report","replication","rejoin","counterplea"],"entry":[{"word":"response","reverse_translation":["ответ","реакция","отклик","чувствительность","ответное чувство"],"synset_id":[3],"score":0.20316233},{"word":"answer","reverse_translation":["ответ","решение","возражение","реакция","письменные объяснения","дуплика"],"synset_id":[3],"score":0.17929012},{"word":"reply","reverse_translation":["ответ","реплика","ответ на контрмеморандум","ответ истца на возражение по иску","отчет"],"synset_id":[3],"score":0.070211023},{"word":"return","reverse_translation":["возврат","возвращение","ответ","рентабельность","прибыль","доход"],"synset_id":[1,6],"score":0.0043503456},{"word":"rejoinder","reverse_translation":["возражение","ответ","объединение","вторичное возражение ответчика","вторая состязательная бумага ответчика","дуплика"],"synset_id":[1],"score":0.000105558},{"word":"report","reverse_translation":["доклад","отчет","сообщение","протокол","рапорт","ответ"],"synset_id":[5],"score":9.6111653e-05},{"word":"replication","reverse_translation":["копирование","реплика","ответ","репродукция","копия","возражение"],"synset_id":[1],"score":8.4818232e-05},{"word":"rejoin","reverse_translation":["ответ"],"synset_id":[6],"score":3.9054989e-06},{"word":"counterplea","reverse_translation":["возражение","ответ"],"synset_id":[2],"score":1.9638082e-06}]},{"pos":"abbreviation","terms":["ans"],"entry":[{"word":"ans","reverse_translation":["ответ"],"synset_id":[4],"score":7.8444042e-05}]}],"src":"ru","server_time":2}
Отсюда задача: написать функцию, которая будет получать подобную строку в виде входного параметра и возвращать созданный из неё объект. Я, собственно, её уже решил, мне она показалась интересной, возможно, кто-то ещё захочет испытать свои силы.