Associative array question when the data is from the web

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
AHKStudent
Posts: 1472
Joined: 05 May 2018, 12:23

Associative array question when the data is from the web

02 Jun 2020, 22:50

If I create this script it works

Code: Select all

test := {"ItemN":625,"Digital":"Both","LocalDel":"Check"}
msgbox, % test.ItemN
However, if I use URLdownloadtofile and get that exact string {"ItemN":625,"Digital":"Both","LocalDel":"Check"} it does not work.

In fact my script doesn't even see the data as anything other than a string, it doesn't respond to any object queries.

Another thing I tested

Code: Select all

FileDelete, atestfile.txt
str := {"ItemN":625,"Digital":"Both","LocalDel":"Check"}
FileAppend, %str%, atestfile.txt
; this works
msgbox, % str.ItemN

; this does not
FileRead, testaa, atestfile.txt
msgbox, % testaa.ItemN
ExitApp
I must be missing something very fundamental about how these arrays work
gregster
Posts: 8921
Joined: 30 Sep 2013, 06:48

Re: Associative array question when the data is from the web

03 Jun 2020, 01:18

You download the information as a string, not as an object - that's normal. But you could use the JSON.Load() method from Coco's JSON library to load the JSON string into an AHK object.
(to transform a JSON-like AHK object (back) to a string, which - for example - could be saved to file, you could use JSON.Dump() instead.)

Other JSON libraries should have similar methods/functions.
AHKStudent
Posts: 1472
Joined: 05 May 2018, 12:23

Re: Associative array question when the data is from the web

03 Jun 2020, 01:28

gregster wrote:
03 Jun 2020, 01:18
You download the information as a string, not as an object - that's normal. But you could use the JSON.Load() method from Coco's JSON library to load the JSON string into an AHK object.
(to transform a JSON-like AHK object (back) to a string, which - for example - could be saved to file, you could use JSON.Dump() instead.)

Other JSON libraries should have similar methods/functions.
really hoped to avoid using libraries for this one

thanks for the explanation
gregster
Posts: 8921
Joined: 30 Sep 2013, 06:48

Re: Associative array question when the data is from the web

03 Jun 2020, 01:36

I mean, there are also function versions of Coco's Class (same topic: look for Jxon), if you don't want to use a class. But somehow you need to parse the string into an object.
Of course, if you are only interested in a single value, you could probably just parse the string via RegEx or something like that. But usually, it is nicer to work with the object.
AHKStudent
Posts: 1472
Joined: 05 May 2018, 12:23

Re: Associative array question when the data is from the web

03 Jun 2020, 01:40

gregster wrote:
03 Jun 2020, 01:36
I mean, there are also function versions of Coco's Class (same topic: look for Jxon), if you don't want to use a class. But somehow you need to parse the string into an object.
Of course, if you are only interested in a single value, you could probably just parse the string via RegEx or something like that. But usually, it is nicer to work with the object.
I agree its so much better to work with the object, my script now uses a regex to get the data.
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: Associative array question when the data is from the web

03 Jun 2020, 09:45

if the string had contained a function definition instead, would u have expected to just be able to call the function as though it were already a hardcoded part of ur script? same thing applies

ahk_h can do this "natively" with AddScript()
but that still falls into the "using libraries" category
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Associative array question when the data is from the web

03 Jun 2020, 09:53

Without libraries:

Code: Select all

str = {"ItemN":625,"Digital":"Both","LocalDel":"Check"}
jsObj := GetJS().("(" . str . ")")
MsgBox, % jsObj.ItemN

GetJS() {
   static doc := ComObjCreate("htmlfile")
         , __ := doc.write("<meta http-equiv=""X-UA-Compatible"" content=""IE=9"">")
         , JS := ObjBindMethod(doc.parentWindow, "eval")
   Return JS
}
User avatar
Chunjee
Posts: 1402
Joined: 18 Apr 2014, 19:05
Contact:

Re: Associative array question when the data is from the web

03 Jun 2020, 10:48

AHKStudent wrote:
03 Jun 2020, 01:28
really hoped to avoid using libraries for this one
total refusal to use libraries isn't normal
but with ahk it is



:think:
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: Associative array question when the data is from the web

03 Jun 2020, 10:53

teadrinker wrote:
03 Jun 2020, 09:53
Without libraries:
Spoiler
SOTE
Posts: 1426
Joined: 15 Jun 2015, 06:21

Re: Associative array question when the data is from the web

03 Jun 2020, 11:29

AHKStudent wrote:
03 Jun 2020, 01:28
really hoped to avoid using libraries for this one
thanks for the explanation
The Jxon functions (for JSON) can be simply added to the bottom of a script, if you don't want to use #Include. I'm among those folks that prefer functions in general, over classes, unless it can't be helped (which is rare in AHK, and hybrid languages like JavaScript, Object Pascal, etc...).

I can somewhat understand where you might be coming from, if a library is particularly big, messy, or contains things that you don't need. Though sometimes the issue is that the user doesn't understand the code or coding style used in the library, but that can be a great opportunity for studying or learning about those different coding styles. Lastly, you can always cut out code that you don't need or modify it to make it more suitable for your purposes.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Associative array question when the data is from the web

03 Jun 2020, 13:00

Chunjee wrote:
03 Jun 2020, 10:48
total refusal to use libraries isn't normal
but with ahk it is
:think:
We just like to share code here, we don't want to actually use it ;). Nice one teadrinker, and swagfag :lol: .

Sorry for off topic, cheers.
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Associative array question when the data is from the web

03 Jun 2020, 13:32

Another one, still without libraries :)

Code: Select all

str = {"ItemN":625,"Digital":"Both","LocalDel":"Check"}
jsObj := GetJS().("(" . str . ")")
MsgBox, % jsObj.ItemN

ahkObj := {}
keys := jsObj.GetKeys()
Loop % keys.length {
   key := keys[A_Index - 1]
   ahkObj[key] := jsObj[key]
}

for k, v in ahkObj
   MsgBox, % k . ": " . v

GetJS() {
   static doc, JS
   if !doc {
      GetKeysFunc =
      (
         Object.prototype.GetKeys = function () {
            var keys = []
            for (var k in this)
               if (this.hasOwnProperty(k))
                  keys.push(k)
            return keys
         }
      )
      doc := ComObjCreate("htmlfile")
      doc.write("<meta http-equiv=""X-UA-Compatible"" content=""IE=9"">")
      JS := ObjBindMethod(doc.parentWindow, "eval")
      JS.(GetKeysFunc)
   }
   Return JS
}
AHKStudent
Posts: 1472
Joined: 05 May 2018, 12:23

Re: Associative array question when the data is from the web

03 Jun 2020, 18:52

thanks everyone, @teadrinker ill probably use that just because I can spend some time learning how that works
User avatar
kczx3
Posts: 1640
Joined: 06 Oct 2015, 21:39

Re: Associative array question when the data is from the web

03 Jun 2020, 21:19

teadrinker wrote:
03 Jun 2020, 09:53
Without libraries:

Code: Select all

str = {"ItemN":625,"Digital":"Both","LocalDel":"Check"}
jsObj := GetJS().("(" . str . ")")
MsgBox, % jsObj.ItemN

GetJS() {
   static doc := ComObjCreate("htmlfile")
         , __ := doc.write("<meta http-equiv=""X-UA-Compatible"" content=""IE=9"">")
         , JS := ObjBindMethod(doc.parentWindow, "eval")
   Return JS
}
This doesn’t actually return an AHK object or array though...
User avatar
kczx3
Posts: 1640
Joined: 06 Oct 2015, 21:39

Re: Associative array question when the data is from the web

04 Jun 2020, 07:24

Just think it’s important for people to understand that
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Associative array question when the data is from the web

04 Jun 2020, 07:38

This is probably the easiest way to obtain an AHK object from a JSON string:

Code: Select all

json = {"ItemN": 625, "Digital": ["", "", {"key": "value"}], "LocalDel": "Check"}
ahkObj := JsonToAHK(json)
MsgBox, % ahkObj["Digital", 3, "key"]

JsonToAHK(json, rec := false) {
   static doc := ComObjCreate("htmlfile")
         , __ := doc.write("<meta http-equiv=""X-UA-Compatible"" content=""IE=9"">")
         , JS := doc.parentWindow
   if !rec
      obj := %A_ThisFunc%(JS.eval("(" . json . ")"), true)
   else if !IsObject(json)
      obj := json
   else if JS.Object.prototype.toString.call(json) == "[object Array]" {
      obj := []
      Loop % json.length
         obj.Push( %A_ThisFunc%(json[A_Index - 1], true) )
   }
   else {
      obj := {}
      keys := JS.Object.keys(json)
      Loop % keys.length {
         k := keys[A_Index - 1]
         obj[k] := %A_ThisFunc%(json[k], true)
      }
   }
   Return obj
}
magusneo
Posts: 45
Joined: 30 Sep 2013, 06:34

Re: Associative array question when the data is from the web

29 Jul 2021, 09:34

teadrinker wrote:
04 Jun 2020, 07:38
This is probably the easiest way to obtain an AHK object from a JSON string:

Code: Select all

json = {"ItemN": 625, "Digital": ["", "", {"key": "value"}], "LocalDel": "Check"}
ahkObj := JsonToAHK(json)
MsgBox, % ahkObj["Digital", 3, "key"]

JsonToAHK(json, rec := false) {
   static doc := ComObjCreate("htmlfile")
         , __ := doc.write("<meta http-equiv=""X-UA-Compatible"" content=""IE=9"">")
         , JS := doc.parentWindow
   if !rec
      obj := %A_ThisFunc%(JS.eval("(" . json . ")"), true)
   else if !IsObject(json)
      obj := json
   else if JS.Object.prototype.toString.call(json) == "[object Array]" {
      obj := []
      Loop % json.length
         obj.Push( %A_ThisFunc%(json[A_Index - 1], true) )
   }
   else {
      obj := {}
      keys := JS.Object.keys(json)
      Loop % keys.length {
         k := keys[A_Index - 1]
         obj[k] := %A_ThisFunc%(json[k], true)
      }
   }
   Return obj
}
Can it work under IE7/8?
It shows "0x80020006 unknown name,Specifically:eval" error under IE8.
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Associative array question when the data is from the web

29 Jul 2021, 13:02

teadrinker, why do You prefer to use eval but not json object?
magusneo, exactly this script You cannot use because Object.keys method You can use from IE9.
But eval You can use also in earlier versions of IE with this trick:

Code: Select all

str = {"ItemN":625,"Digital":"Both","LocalDel":"Check"}
jsObj := GetJS().("(" . str . ")")
MsgBox, % jsObj.ItemN

GetJS() {
   static doc := ComObjCreate("htmlfile")
         , __ := doc.write("<meta http-equiv=""X-UA-Compatible"" content=""IE=9"">")
         , JS := doc.parentWindow
   JS.execScript(" ")   ; Initializing the JavaScript interpreter for IE < IE9
   Return ObjBindMethod(JS, "eval")
}

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: RussF, skeerrt, vmech and 145 guests