Help Retrieving Specific Text From Api (Bible Verse) Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
cacw
Posts: 3
Joined: 22 Jun 2018, 11:18
Contact:

Help Retrieving Specific Text From Api (Bible Verse)

22 Jun 2018, 11:32

Good day!

Need help with a change and update for this code. The use is for pasting simple text verse while typing.

Code: Select all

{
#b::
	Input, ref, V, {enter}{tab}
	If InStr(ErrorLevel, "EndKey:")
	{
		url := "https://api.esv.org/v3/passage/text/?q=" . ref
		url := url . "&output-format=plain-text"
		url := url . "&include-passage-references=false"
		url := url . "&include-headings=false"
		url := url . "&include-subheadings=false"
		url := url . "&include-passage-horizontal-lines=0"
		url := url . "&include-heading-horizontal-lines=0"
		url := url . "&line-length=0"
		url := url . "&include-footnotes=false"
		url := url . "include-short-copyright=false"
		url := url . "indent-paragraphs=0"

		WinHTTP := ComObjCreate("WinHTTP.WinHttpRequest.5.1")
		WinHTTP.Open("GET", url, 0)
		WinHTTP.SetRequestHeader("Content-Type", "application/json")
		WinHTTP.SetRequestHeader("Authorization", "Token XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX)
		Body = {}
		WinHTTP.Send()
		
		ClipSaved := ClipboardAll ; backup clipboard
		Clipboard := WinHTTP.ResponseText

		Send ^v

		Sleep 500
		Clipboard := ClipSaved ; restore clipboard
		ClipSaved = ; free memory

	    Return
	}
Return
}
This is the response text:

Code: Select all

{"query":"Jn1:1","canonical":"John 1:1","parsed":[[43001001,43001001]],"passage_meta":[{"canonical":"John 1:1","chapter_start":[43001001,43001051],"chapter_end":[43001001,43001051],"prev_verse":42024053,"next_verse":43001002,"prev_chapter":[42024001,42024053],"next_chapter":[43002001,43002025]}],"passages":["  [1] In the beginning was the Word, and the Word was with God, and the Word was God. (ESV)"]}
Any suggestions?
User avatar
FanaticGuru
Posts: 1906
Joined: 30 Sep 2013, 22:25

Re: Help Retrieving Specific Text From Api (Bible Verse)  Topic is solved

22 Jun 2018, 12:59

cacw wrote:This is the response text:

Code: Select all

{"query":"Jn1:1","canonical":"John 1:1","parsed":[[43001001,43001001]],"passage_meta":[{"canonical":"John 1:1","chapter_start":[43001001,43001051],"chapter_end":[43001001,43001051],"prev_verse":42024053,"next_verse":43001002,"prev_chapter":[42024001,42024053],"next_chapter":[43002001,43002025]}],"passages":["  [1] In the beginning was the Word, and the Word was with God, and the Word was God. (ESV)"]}
Any suggestions?
I assume you just want the passage out of that.

Code: Select all

;~ Clipboard := WinHTTP.ResponseText
; Replace with vvvvv
Needle = \Q"passages":["  [1] \E(.*?)"
RegExMatch(WinHTTP.ResponseText, Needle, Match)
Clipboard := Match1
This might require some actual testing. RegEx patterns are very specific and this one is designed with very little flexibility but it is very likely the response is very consistent.

The response is a JSON string and there are libraries that would allow you to extract information from this string in a much more robust way.

FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks
cacw
Posts: 3
Joined: 22 Jun 2018, 11:18
Contact:

Re: Help Retrieving Specific Text From Api (Bible Verse)

25 Jun 2018, 09:07

Wow, thanks for the help -- I was not familiar with the Needle function at all.

However, it does give me an error if I request text with quotations (" " )in it, and it does not return verses that contain quotations in it.

Hosea 1:1-3
The word of the LORD that came to Hosea, the son of Beeri, in the days of Uzziah, Jotham, Ahaz, and Hezekiah, kings of Judah, and in the days of Jeroboam the son of Joash, king of Israel.\n\n [2] When the LORD first spoke through Hosea, the LORD said to Hosea, “Go, take to yourself a wife of whoredom and have children of whoredom, for the land commits great whoredom by forsaking the LORD.” [3] So he went and took Gomer, the daughter of Diblaim, and she conceived and bore him a son. (ESV)

Appreciate your help!
User avatar
FanaticGuru
Posts: 1906
Joined: 30 Sep 2013, 22:25

Re: Help Retrieving Specific Text From Api (Bible Verse)

25 Jun 2018, 14:39

cacw wrote:Wow, thanks for the help -- I was not familiar with the Needle function at all.

However, it does give me an error if I request text with quotations (" " )in it, and it does not return verses that contain quotations in it.

Hosea 1:1-3
The word of the LORD that came to Hosea, the son of Beeri, in the days of Uzziah, Jotham, Ahaz, and Hezekiah, kings of Judah, and in the days of Jeroboam the son of Joash, king of Israel.\n\n [2] When the LORD first spoke through Hosea, the LORD said to Hosea, “Go, take to yourself a wife of whoredom and have children of whoredom, for the land commits great whoredom by forsaking the LORD.” [3] So he went and took Gomer, the daughter of Diblaim, and she conceived and bore him a son. (ESV)

Appreciate your help!
If you post the whole response text that is returned, I might be able to make a needle that will pull out just the passage.

FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks
cacw
Posts: 3
Joined: 22 Jun 2018, 11:18
Contact:

Re: Help Retrieving Specific Text From Api (Bible Verse)

26 Jun 2018, 08:56

Here are two:

How can they be taken?

Code: Select all

Jn1:1
{"query":"Jn1:1","canonical":"John 1:1","parsed":[[43001001,43001001]],"passage_meta":[{"canonical":"John 1:1","chapter_start":[43001001,43001051],"chapter_end":[43001001,43001051],"prev_verse":42024053,"next_verse":43001002,"prev_chapter":[42024001,42024053],"next_chapter":[43002001,43002025]}],"passages":["  [1] In the beginning was the Word, and the Word was with God, and the Word was God. (ESV)"]}

Ps19
{"query":"Ps19","canonical":"Psalm 19","parsed":[[19019001,19019014]],"passage_meta":[{"canonical":"Psalm 19","chapter_start":[19019001,19019014],"chapter_end":[19019001,19019014],"prev_verse":19018050,"next_verse":19020001,"prev_chapter":[19018001,19018050],"next_chapter":[19020001,19020009]}],"passages":["To the choirmaster. A Psalm of David.\n\n    [1] The heavens declare the glory of God,\n        and the sky above(1) proclaims his handiwork.\n    [2] Day to day pours out speech,\n        and night to night reveals knowledge.\n    [3] There is no speech, nor are there words,\n        whose voice is not heard.\n    [4] Their voice(2) goes out through all the earth,\n        and their words to the end of the world.\n    In them he has set a tent for the sun,\n    [5]     which comes out like a bridegroom leaving his chamber,\n        and, like a strong man, runs its course with joy.\n    [6] Its rising is from the end of the heavens,\n        and its circuit to the end of them,\n        and there is nothing hidden from its heat.\n    \n    \n    [7] The law of the LORD is perfect,(3)\n        reviving the soul;\n    the testimony of the LORD is sure,\n        making wise the simple;\n    [8] the precepts of the LORD are right,\n        rejoicing the heart;\n    the commandment of the LORD is pure,\n        enlightening the eyes;\n    [9] the fear of the LORD is clean,\n        enduring forever;\n    the rules(4) of the LORD are true,\n        and righteous altogether.\n    [10] More to be desired are they than gold,\n        even much fine gold;\n    sweeter also than honey\n        and drippings of the honeycomb.\n    [11] Moreover, by them is your servant warned;\n        in keeping them there is great reward.\n    \n    \n    [12] Who can discern his errors?\n        Declare me innocent from hidden faults.\n    [13] Keep back your servant also from presumptuous sins;\n        let them not have dominion over me!\n    Then I shall be blameless,\n        and innocent of great transgression.\n    \n    \n    [14] Let the words of my mouth and the meditation of my heart\n        be acceptable in your sight,\n        O LORD, my rock and my redeemer.\n    \n\nFootnotes\n\n(1) 19:1 Hebrew *the expanse*; compare Genesis 1:6–8\n\n(2) 19:4 Or *Their measuring line*\n\n(3) 19:7 Or *blameless*\n\n(4) 19:9 Or *just decrees*\n (ESV)"]}
User avatar
FanaticGuru
Posts: 1906
Joined: 30 Sep 2013, 22:25

Re: Help Retrieving Specific Text From Api (Bible Verse)

26 Jun 2018, 13:04

cacw wrote:Here are two:

How can they be taken?

Code: Select all

Jn1:1
{"query":"Jn1:1","canonical":"John 1:1","parsed":[[43001001,43001001]],"passage_meta":[{"canonical":"John 1:1","chapter_start":[43001001,43001051],"chapter_end":[43001001,43001051],"prev_verse":42024053,"next_verse":43001002,"prev_chapter":[42024001,42024053],"next_chapter":[43002001,43002025]}],"passages":["  [1] In the beginning was the Word, and the Word was with God, and the Word was God. (ESV)"]}

Ps19
{"query":"Ps19","canonical":"Psalm 19","parsed":[[19019001,19019014]],"passage_meta":[{"canonical":"Psalm 19","chapter_start":[19019001,19019014],"chapter_end":[19019001,19019014],"prev_verse":19018050,"next_verse":19020001,"prev_chapter":[19018001,19018050],"next_chapter":[19020001,19020009]}],"passages":["To the choirmaster. A Psalm of David.\n\n    [1] The heavens declare the glory of God,\n        and the sky above(1) proclaims his handiwork.\n    [2] Day to day pours out speech,\n        and night to night reveals knowledge.\n    [3] There is no speech, nor are there words,\n        whose voice is not heard.\n    [4] Their voice(2) goes out through all the earth,\n        and their words to the end of the world.\n    In them he has set a tent for the sun,\n    [5]     which comes out like a bridegroom leaving his chamber,\n        and, like a strong man, runs its course with joy.\n    [6] Its rising is from the end of the heavens,\n        and its circuit to the end of them,\n        and there is nothing hidden from its heat.\n    \n    \n    [7] The law of the LORD is perfect,(3)\n        reviving the soul;\n    the testimony of the LORD is sure,\n        making wise the simple;\n    [8] the precepts of the LORD are right,\n        rejoicing the heart;\n    the commandment of the LORD is pure,\n        enlightening the eyes;\n    [9] the fear of the LORD is clean,\n        enduring forever;\n    the rules(4) of the LORD are true,\n        and righteous altogether.\n    [10] More to be desired are they than gold,\n        even much fine gold;\n    sweeter also than honey\n        and drippings of the honeycomb.\n    [11] Moreover, by them is your servant warned;\n        in keeping them there is great reward.\n    \n    \n    [12] Who can discern his errors?\n        Declare me innocent from hidden faults.\n    [13] Keep back your servant also from presumptuous sins;\n        let them not have dominion over me!\n    Then I shall be blameless,\n        and innocent of great transgression.\n    \n    \n    [14] Let the words of my mouth and the meditation of my heart\n        be acceptable in your sight,\n        O LORD, my rock and my redeemer.\n    \n\nFootnotes\n\n(1) 19:1 Hebrew *the expanse*; compare Genesis 1:6–8\n\n(2) 19:4 Or *Their measuring line*\n\n(3) 19:7 Or *blameless*\n\n(4) 19:9 Or *just decrees*\n (ESV)"]}
That is pretty varied results.

You are probably better off just using a full fletch JSON library.

Code: Select all

Data1 = {"query":"Jn1:1","canonical":"John 1:1","parsed":[[43001001,43001001]],"passage_meta":[{"canonical":"John 1:1","chapter_start":[43001001,43001051],"chapter_end":[43001001,43001051],"prev_verse":42024053,"next_verse":43001002,"prev_chapter":[42024001,42024053],"next_chapter":[43002001,43002025]}],"passages":["  [1] In the beginning was the Word, and the Word was with God, and the Word was God. (ESV)"]}

Data2 = {"query":"Ps19","canonical":"Psalm 19","parsed":[[19019001,19019014]],"passage_meta":[{"canonical":"Psalm 19","chapter_start":[19019001,19019014],"chapter_end":[19019001,19019014],"prev_verse":19018050,"next_verse":19020001,"prev_chapter":[19018001,19018050],"next_chapter":[19020001,19020009]}],"passages":["To the choirmaster. A Psalm of David.\n\n    [1] The heavens declare the glory of God,\n        and the sky above(1) proclaims his handiwork.\n    [2] Day to day pours out speech,\n        and night to night reveals knowledge.\n    [3] There is no speech, nor are there words,\n        whose voice is not heard.\n    [4] Their voice(2) goes out through all the earth,\n        and their words to the end of the world.\n    In them he has set a tent for the sun,\n    [5]     which comes out like a bridegroom leaving his chamber,\n        and, like a strong man, runs its course with joy.\n    [6] Its rising is from the end of the heavens,\n        and its circuit to the end of them,\n        and there is nothing hidden from its heat.\n    \n    \n    [7] The law of the LORD is perfect,(3)\n        reviving the soul;\n    the testimony of the LORD is sure,\n        making wise the simple;\n    [8] the precepts of the LORD are right,\n        rejoicing the heart;\n    the commandment of the LORD is pure,\n        enlightening the eyes;\n    [9] the fear of the LORD is clean,\n        enduring forever;\n    the rules(4) of the LORD are true,\n        and righteous altogether.\n    [10] More to be desired are they than gold,\n        even much fine gold;\n    sweeter also than honey\n        and drippings of the honeycomb.\n    [11] Moreover, by them is your servant warned;\n        in keeping them there is great reward.\n    \n    \n    [12] Who can discern his errors?\n        Declare me innocent from hidden faults.\n    [13] Keep back your servant also from presumptuous sins;\n        let them not have dominion over me!\n    Then I shall be blameless,\n        and innocent of great transgression.\n    \n    \n    [14] Let the words of my mouth and the meditation of my heart\n        be acceptable in your sight,\n        O LORD, my rock and my redeemer.\n    \n\nFootnotes\n\n(1) 19:1 Hebrew *the expanse*; compare Genesis 1:6â??8\n\n(2) 19:4 Or *Their measuring line*\n\n(3) 19:7 Or *blameless*\n\n(4) 19:9 Or *just decrees*\n (ESV)"]}

oJson := Json.Load(Data1)
MsgBox % oJson.Passages[1] ; the data is setup to support multiple passages so this gets the first one

oJson := Json.Load(Data2)
MsgBox % oJson.Passages[1]
MsgBox % oJson.Query	; data is setup to support only one of this property so do not have to designate which one
MsgBox % oJson.Canonical

; vvvvv  DO NOT NEED TO UNDERSTAND ANYTHING BELOW HERE  vvvvvv
/**
 * Lib: JSON.ahk
 *     JSON lib for AutoHotkey.
 * Version:
 *     v2.1.3 [updated 04/18/2016 (MM/DD/YYYY)]
 * License:
 *     WTFPL [http://wtfpl.net/]
 * Requirements:
 *     Latest version of AutoHotkey (v1.1+ or v2.0-a+)
 * Installation:
 *     Use #Include JSON.ahk or copy into a function library folder and then
 *     use #Include <JSON>
 * Links:
 *     GitHub:     - https://github.com/cocobelgica/AutoHotkey-JSON
 *     Forum Topic - http://goo.gl/r0zI8t
 *     Email:      - cocobelgica <at> gmail <dot> com
 */


/**
 * Class: JSON
 *     The JSON object contains methods for parsing JSON and converting values
 *     to JSON. Callable - NO; Instantiable - YES; Subclassable - YES;
 *     Nestable(via #Include) - NO.
 * Methods:
 *     Load() - see relevant documentation before method definition header
 *     Dump() - see relevant documentation before method definition header
 */
class JSON
{
	/**
	 * Method: Load
	 *     Parses a JSON string into an AHK value
	 * Syntax:
	 *     value := JSON.Load( text [, reviver ] )
	 * Parameter(s):
	 *     value      [retval] - parsed value
	 *     text    [in, ByRef] - JSON formatted string
	 *     reviver   [in, opt] - function object, similar to JavaScript's
	 *                           JSON.parse() 'reviver' parameter
	 */
	class Load extends JSON.Functor
	{
		Call(self, ByRef text, reviver:="")
		{
			this.rev := IsObject(reviver) ? reviver : false
		; Object keys(and array indices) are temporarily stored in arrays so that
		; we can enumerate them in the order they appear in the document/text instead
		; of alphabetically. Skip if no reviver function is specified.
			this.keys := this.rev ? {} : false

			static quot := Chr(34), bashq := "\" . quot
			     , json_value := quot . "{[01234567890-tfn"
			     , json_value_or_array_closing := quot . "{[]01234567890-tfn"
			     , object_key_or_object_closing := quot . "}"

			key := ""
			is_key := false
			root := {}
			stack := [root]
			next := json_value
			pos := 0

			while ((ch := SubStr(text, ++pos, 1)) != "") {
				if InStr(" `t`r`n", ch)
					continue
				if !InStr(next, ch, 1)
					this.ParseError(next, text, pos)

				holder := stack[1]
				is_array := holder.IsArray

				if InStr(",:", ch) {
					next := (is_key := !is_array && ch == ",") ? quot : json_value

				} else if InStr("}]", ch) {
					ObjRemoveAt(stack, 1)
					next := stack[1]==root ? "" : stack[1].IsArray ? ",]" : ",}"

				} else {
					if InStr("{[", ch) {
					; Check if Array() is overridden and if its return value has
					; the 'IsArray' property. If so, Array() will be called normally,
					; otherwise, use a custom base object for arrays
						static json_array := Func("Array").IsBuiltIn || ![].IsArray ? {IsArray: true} : 0
					
					; sacrifice readability for minor(actually negligible) performance gain
						(ch == "{")
							? ( is_key := true
							  , value := {}
							  , next := object_key_or_object_closing )
						; ch == "["
							: ( value := json_array ? new json_array : []
							  , next := json_value_or_array_closing )
						
						ObjInsertAt(stack, 1, value)

						if (this.keys)
							this.keys[value] := []
					
					} else {
						if (ch == quot) {
							i := pos
							while (i := InStr(text, quot,, i+1)) {
								value := StrReplace(SubStr(text, pos+1, i-pos-1), "\\", "\u005c")

								static tail := A_AhkVersion<"2" ? 0 : -1
								if (SubStr(value, tail) != "\")
									break
							}

							if (!i)
								this.ParseError("'", text, pos)

							  value := StrReplace(value,  "\/",  "/")
							, value := StrReplace(value, bashq, quot)
							, value := StrReplace(value,  "\b", "`b")
							, value := StrReplace(value,  "\f", "`f")
							, value := StrReplace(value,  "\n", "`n")
							, value := StrReplace(value,  "\r", "`r")
							, value := StrReplace(value,  "\t", "`t")

							pos := i ; update pos
							
							i := 0
							while (i := InStr(value, "\",, i+1)) {
								if !(SubStr(value, i+1, 1) == "u")
									this.ParseError("\", text, pos - StrLen(SubStr(value, i+1)))

								uffff := Abs("0x" . SubStr(value, i+2, 4))
								if (A_IsUnicode || uffff < 0x100)
									value := SubStr(value, 1, i-1) . Chr(uffff) . SubStr(value, i+6)
							}

							if (is_key) {
								key := value, next := ":"
								continue
							}
						
						} else {
							value := SubStr(text, pos, i := RegExMatch(text, "[\]\},\s]|$",, pos)-pos)

							static number := "number", integer :="integer"
							if value is %number%
							{
								if value is %integer%
									value += 0
							}
							else if (value == "true" || value == "false")
								value := %value% + 0
							else if (value == "null")
								value := ""
							else
							; we can do more here to pinpoint the actual culprit
							; but that's just too much extra work.
								this.ParseError(next, text, pos, i)

							pos += i-1
						}

						next := holder==root ? "" : is_array ? ",]" : ",}"
					} ; If InStr("{[", ch) { ... } else

					is_array? key := ObjPush(holder, value) : holder[key] := value

					if (this.keys && this.keys.HasKey(holder))
						this.keys[holder].Push(key)
				}
			
			} ; while ( ... )

			return this.rev ? this.Walk(root, "") : root[""]
		}

		ParseError(expect, ByRef text, pos, len:=1)
		{
			static quot := Chr(34), qurly := quot . "}"
			
			line := StrSplit(SubStr(text, 1, pos), "`n", "`r").Length()
			col := pos - InStr(text, "`n",, -(StrLen(text)-pos+1))
			msg := Format("{1}`n`nLine:`t{2}`nCol:`t{3}`nChar:`t{4}"
			,     (expect == "")     ? "Extra data"
			    : (expect == "'")    ? "Unterminated string starting at"
			    : (expect == "\")    ? "Invalid \escape"
			    : (expect == ":")    ? "Expecting ':' delimiter"
			    : (expect == quot)   ? "Expecting object key enclosed in double quotes"
			    : (expect == qurly)  ? "Expecting object key enclosed in double quotes or object closing '}'"
			    : (expect == ",}")   ? "Expecting ',' delimiter or object closing '}'"
			    : (expect == ",]")   ? "Expecting ',' delimiter or array closing ']'"
			    : InStr(expect, "]") ? "Expecting JSON value or array closing ']'"
			    :                      "Expecting JSON value(string, number, true, false, null, object or array)"
			, line, col, pos)

			static offset := A_AhkVersion<"2" ? -3 : -4
			throw Exception(msg, offset, SubStr(text, pos, len))
		}

		Walk(holder, key)
		{
			value := holder[key]
			if IsObject(value) {
				for i, k in this.keys[value] {
					; check if ObjHasKey(value, k) ??
					v := this.Walk(value, k)
					if (v != JSON.Undefined)
						value[k] := v
					else
						ObjDelete(value, k)
				}
			}
			
			return this.rev.Call(holder, key, value)
		}
	}

	/**
	 * Method: Dump
	 *     Converts an AHK value into a JSON string
	 * Syntax:
	 *     str := JSON.Dump( value [, replacer, space ] )
	 * Parameter(s):
	 *     str        [retval] - JSON representation of an AHK value
	 *     value          [in] - any value(object, string, number)
	 *     replacer  [in, opt] - function object, similar to JavaScript's
	 *                           JSON.stringify() 'replacer' parameter
	 *     space     [in, opt] - similar to JavaScript's JSON.stringify()
	 *                           'space' parameter
	 */
	class Dump extends JSON.Functor
	{
		Call(self, value, replacer:="", space:="")
		{
			this.rep := IsObject(replacer) ? replacer : ""

			this.gap := ""
			if (space) {
				static integer := "integer"
				if space is %integer%
					Loop, % ((n := Abs(space))>10 ? 10 : n)
						this.gap .= " "
				else
					this.gap := SubStr(space, 1, 10)

				this.indent := "`n"
			}

			return this.Str({"": value}, "")
		}

		Str(holder, key)
		{
			value := holder[key]

			if (this.rep)
				value := this.rep.Call(holder, key, ObjHasKey(holder, key) ? value : JSON.Undefined)

			if IsObject(value) {
			; Check object type, skip serialization for other object types such as
			; ComObject, Func, BoundFunc, FileObject, RegExMatchObject, Property, etc.
				static type := A_AhkVersion<"2" ? "" : Func("Type")
				if (type ? type.Call(value) == "Object" : ObjGetCapacity(value) != "") {
					if (this.gap) {
						stepback := this.indent
						this.indent .= this.gap
					}

					is_array := value.IsArray
				; Array() is not overridden, rollback to old method of
				; identifying array-like objects. Due to the use of a for-loop
				; sparse arrays such as '[1,,3]' are detected as objects({}). 
					if (!is_array) {
						for i in value
							is_array := i == A_Index
						until !is_array
					}

					str := ""
					if (is_array) {
						Loop, % value.Length() {
							if (this.gap)
								str .= this.indent
							
							v := this.Str(value, A_Index)
							str .= (v != "") ? v . "," : "null,"
						}
					} else {
						colon := this.gap ? ": " : ":"
						for k in value {
							v := this.Str(value, k)
							if (v != "") {
								if (this.gap)
									str .= this.indent

								str .= this.Quote(k) . colon . v . ","
							}
						}
					}

					if (str != "") {
						str := RTrim(str, ",")
						if (this.gap)
							str .= stepback
					}

					if (this.gap)
						this.indent := stepback

					return is_array ? "[" . str . "]" : "{" . str . "}"
				}
			
			} else ; is_number ? value : "value"
				return ObjGetCapacity([value], 1)=="" ? value : this.Quote(value)
		}

		Quote(string)
		{
			static quot := Chr(34), bashq := "\" . quot

			if (string != "") {
				  string := StrReplace(string,  "\",  "\\")
				; , string := StrReplace(string,  "/",  "\/") ; optional in ECMAScript
				, string := StrReplace(string, quot, bashq)
				, string := StrReplace(string, "`b",  "\b")
				, string := StrReplace(string, "`f",  "\f")
				, string := StrReplace(string, "`n",  "\n")
				, string := StrReplace(string, "`r",  "\r")
				, string := StrReplace(string, "`t",  "\t")

				static rx_escapable := A_AhkVersion<"2" ? "O)[^\x20-\x7e]" : "[^\x20-\x7e]"
				while RegExMatch(string, rx_escapable, m)
					string := StrReplace(string, m.Value, Format("\u{1:04x}", Ord(m.Value)))
			}

			return quot . string . quot
		}
	}

	/**
	 * Property: Undefined
	 *     Proxy for 'undefined' type
	 * Syntax:
	 *     undefined := JSON.Undefined
	 * Remarks:
	 *     For use with reviver and replacer functions since AutoHotkey does not
	 *     have an 'undefined' type. Returning blank("") or 0 won't work since these
	 *     can't be distnguished from actual JSON values. This leaves us with objects.
	 *     Replacer() - the caller may return a non-serializable AHK objects such as
	 *     ComObject, Func, BoundFunc, FileObject, RegExMatchObject, and Property to
	 *     mimic the behavior of returning 'undefined' in JavaScript but for the sake
	 *     of code readability and convenience, it's better to do 'return JSON.Undefined'.
	 *     Internally, the property returns a ComObject with the variant type of VT_EMPTY.
	 */
	Undefined[]
	{
		get {
			static empty := {}, vt_empty := ComObject(0, &empty, 1)
			return vt_empty
		}
	}

	class Functor
	{
		__Call(method, ByRef arg, args*)
		{
		; When casting to Call(), use a new instance of the "function object"
		; so as to avoid directly storing the properties(used across sub-methods)
		; into the "function object" itself.
			if IsObject(method)
				return (new this).Call(method, arg, args*)
			else if (method == "")
				return (new this).Call(arg, args*)
		}
	}
}
You don't really need to understand what all the JSON class is doing. You just need to understand it is turning that JSON string into an AutoHotkey array object.

FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: aitaixy, Anput, dangoscrub, doodles333, joedf, Nerafius and 127 guests