#include-once #include #include Func _json_decode($sJson) local $iIndex = 1 Local $vValue = __json_decode($sJson, $iIndex) Local $error = @error, $extended = @extended If @error = 0 And Not (StringMid($sJson, $iIndex, 1) = '') Then Return SetError(1, @ScriptLineNumber, 'Expected end of string, found: "' & StringMid($sJson, $iIndex, 1) & '" at offset: ' & $iIndex) Return SetError($error, $extended, $vValue) EndFunc Func __json_decode(ByRef $sJson, ByRef $iIndex) Local $vValue While 1 Switch StringMid($sJson, $iIndex, 1) Case '{' $vValue = __json_decode_object($sJson, $iIndex) Case '[' $vValue = __json_decode_array($sJson, $iIndex) Case '"' $vValue = __json_decode_string($sJson, $iIndex) Case '0' To '9', '-' $vValue = __json_decode_number($sJson, $iIndex) Case 't' $vValue = __json_decode_true($sJson, $iIndex) Case 'f' $vValue = __json_decode_false($sJson, $iIndex) Case 'n' $vValue = __json_decode_null($sJson, $iIndex) Case ' ', @LF, @CR, @TAB $iIndex += 1 ContinueLoop Case '' ContinueCase Case Else Return SetError(1, @ScriptLineNumber, 'Unexpected character: "' & StringMid($sJson, $iIndex, 1) & '" at offset: ' & $iIndex) EndSwitch Return SetError(@error, @extended, $vValue) WEnd EndFunc Func __json_decode_object(ByRef $sJson, ByRef $iIndex) $iIndex += 1 Local $object[] Local $key While 1 Switch StringMid($sJson, $iIndex, 1) Case '}' $iIndex += 1 Return $object Case '"' $key = __json_decode_string($sJson, $iIndex) Case ' ', @LF, @CR, @TAB $iIndex += 1 ContinueLoop Case '' ContinueCase Case Else Return SetError(1, @ScriptLineNumber, 'Unexpected character: "' & StringMid($sJson, $iIndex, 1) & '" at offset: ' & $iIndex) EndSwitch While 1 Switch StringMid($sJson, $iIndex, 1) Case ':' $iIndex += 1 ExitLoop Case ' ', @LF, @CR, @TAB $iIndex += 1 Case '' ContinueCase Case Else Return SetError(1, @ScriptLineNumber, 'Unexpected character: "' & StringMid($sJson, $iIndex, 1) & '" at offset: ' & $iIndex) EndSwitch WEnd $object[$key] = __json_decode($sJson, $iIndex) If @error <> 0 Then Return SetError(@error, @extended, $object[$key]) EndIf While 1 Switch StringMid($sJson, $iIndex, 1) Case ',' $iIndex += 1 ExitLoop Case ' ', @LF, @CR, @TAB $iIndex += 1 Case '}' $iIndex += 1 Return $object Case '' ContinueCase Case Else Return SetError(1, @ScriptLineNumber, 'Unexpected character: "' & StringMid($sJson, $iIndex, 1) & '" at offset: ' & $iIndex) EndSwitch WEnd WEnd EndFunc Func __json_decode_string(ByRef $sJson, ByRef $iIndex) $iIndex += 1 Local $string = "" Local $c While 1 $c = StringMid($sJson, $iIndex, 1) $iIndex += 1 Switch $c Case '"' Return $string Case '\' $c = StringMid($sJson, $iIndex, 1) $iIndex += 1 Switch $c Case '"', '\', '/' $string &= $c Case 'b' $string &= Chr(8) Case 'f' $string &= Chr(12) Case 'n' $string &= Chr(10) Case 'r' $string &= Chr(13) Case 't' $string &= Chr(9) Case '' ContinueCase Case Else Return SetError(1, @ScriptLineNumber, 'Unexpected escape character: "' & $c & '" at offset: ' & $iIndex) EndSwitch Case '' Return SetError(1, @ScriptLineNumber, 'Unexpected end of string at offset: ' & $iIndex) Case Else $string &= $c EndSwitch WEnd EndFunc Func __json_decode_array(ByRef $sJson, ByRef $iIndex) $iIndex += 1 Local $array[16] Local $i = 0 While 1 Switch StringMid($sJson, $iIndex, 1) Case ']' Redim $array[$i] $iIndex += 1 Return $array Case ' ', @LF, @CR, @TAB $iIndex += 1 ContinueLoop Case '' Return SetError(1, @ScriptLineNumber, 'Unexpected end of string at offset: ' & $iIndex) Case Else $array[$i] = __json_decode($sJson, $iIndex) If @error <> 0 Then Return SetError(@error, @extended, $array[$i]) EndIf $i+=1 If $i >= UBound($array) Then Redim $array[UBound($array)*2] EndSwitch While 1 Switch StringMid($sJson, $iIndex, 1) Case ',' $iIndex += 1 ExitLoop Case ' ', @LF, @CR, @TAB $iIndex += 1 Case ']' Redim $array[$i] $iIndex += 1 Return $array Case '' ContinueCase Case Else Return SetError(1, @ScriptLineNumber, 'Expected "," or "]", found: "' & StringMid($sJson, $iIndex, 1) & '" at offset: ' & $iIndex) EndSwitch WEnd WEnd EndFunc Func __json_decode_number(ByRef $sJson, ByRef $iIndex) Local $number = "" If StringMid($sJson, $iIndex, 1) = '-' Then $number &= StringMid($sJson, $iIndex, 1) $iIndex += 1 EndIf If Not StringIsDigit(StringMid($sJson, $iIndex, 1)) Then Return SetError(1, @ScriptLineNumber, 'Expected digit, found: "' & StringMid($sJson, $iIndex, 1) & '" at offset: ' & $iIndex) While 1 Switch StringMid($sJson, $iIndex, 1) Case '0' To '9' $number &= StringMid($sJson, $iIndex, 1) $iIndex += 1 ContinueLoop Case Else ExitLoop EndSwitch WEnd ;Fraction If StringMid($sJson, $iIndex, 1) = '.' Then $number &= StringMid($sJson, $iIndex, 1) $iIndex += 1 If Not StringIsDigit(StringMid($sJson, $iIndex, 1)) Then Return SetError(1, @ScriptLineNumber, 'Expected digit, found: "' & StringMid($sJson, $iIndex, 1) & '" at offset: ' & $iIndex) While 1 Switch StringMid($sJson, $iIndex, 1) Case '0' To '9' $number &= StringMid($sJson, $iIndex, 1) $iIndex += 1 ContinueLoop Case Else ExitLoop EndSwitch WEnd EndIf ;Exponent If StringLower(StringMid($sJson, $iIndex, 1)) = 'e' Then $number &= StringMid($sJson, $iIndex, 1) $iIndex += 1 Switch StringMid($sJson, $iIndex, 1) Case '+', '-' $number &= StringMid($sJson, $iIndex, 1) $iIndex += 1 EndSwitch If Not StringIsDigit(StringMid($sJson, $iIndex, 1)) Then Return SetError(1, @ScriptLineNumber, 'Expected digit, found: "' & StringMid($sJson, $iIndex, 1) & '" at offset: ' & $iIndex) While 1 Switch StringMid($sJson, $iIndex, 1) Case '0' To '9' $number &= StringMid($sJson, $iIndex, 1) $iIndex += 1 ContinueLoop Case Else ExitLoop EndSwitch WEnd EndIf Local $value = Execute($number) If @error <> 0 Then Return SetError(1, @ScriptLineNumber, 'Failed to parse number: "' & $value & '" at offset: ' & $iIndex) EndIf Return $value EndFunc Func __json_decode_true(ByRef $sJson, ByRef $iIndex) If Not (StringMid($sJson, $iIndex, 4) == "true") Then Return SetError(1, @ScriptLineNumber, 'Expected "true", found: "' & StringMid($sJson, $iIndex, 4) & '" at offset: ' & $iIndex) EndIf $iIndex += 4 Return True EndFunc Func __json_decode_false(ByRef $sJson, ByRef $iIndex) If Not (StringMid($sJson, $iIndex, 5) == "false") Then Return SetError(1, @ScriptLineNumber, 'Expected "false", found: "' & StringMid($sJson, $iIndex, 5) & '" at offset: ' & $iIndex) EndIf $iIndex += 5 Return False EndFunc Func __json_decode_null(ByRef $sJson, ByRef $iIndex) If Not (StringMid($sJson, $iIndex, 4) == "null") Then Return SetError(1, @ScriptLineNumber, 'Expected "null", found: "' & StringMid($sJson, $iIndex, 4) & '" at offset: ' & $iIndex) EndIf $iIndex += 4 Return Null EndFunc Func _json_encode($vJson, $fnReplacer = Null) If Not IsFunc($fnReplacer) Then $fnReplacer = Null Return __json_encode($vJson, $fnReplacer) EndFunc Func __json_encode(ByRef $v, $fnReplacer) Switch VarGetType($v) Case "Map" Return __json_encode_map($v, $fnReplacer) Case "Array" Return __json_encode_array($v, $fnReplacer) Case "String" Return __json_encode_string($v) Case "Int32" ContinueCase Case "Int64" ContinueCase Case "Double" Return __json_encode_number($v) Case "Bool" Return __json_encode_bool($v) Case "Keyword" If Not ($v = Null) Then ContinueCase Return __json_encode_null($v) Case Else If IsFunc($fnReplacer) Then Return __json_encode(Call($fnReplacer, $v), $iLevel, Null) Return __json_encode_null($v) EndSwitch EndFunc Func __json_encode_map(ByRef $map, $fnReplacer) if UBound($map) = 0 Then Return "{}" Local $sJson = "{" For $key In MapKeys($map) $sJson &= __json_encode_string($key) & ":" & __json_encode($map[$key], $fnReplacer) & "," IF @error <> 0 Then Return SetError(@error, @extended, Null) Next Return StringMid($sJson, 1, StringLen($sJson) - 1) & "}" EndFunc Func __json_encode_array(ByRef $array, $fnReplacer) Local $iDimensions = UBound($array, 0) Local $aIndices[$iDimensions] For $iIndex = 0 To $iDimensions - 1 $aIndices[$iIndex] = 0; Fill array with 0 If UBound($array, $iIndex + 1) = 0 Then; Special handling for array dimention with length 0 Redim $aIndices[$iIndex+1]; Resize array dimentions to first occurence of length zero, as no child elements can exist $iDimensions = $iIndex + 1 Local $sArray = "[]" ; The loop will wrap the child element(s) in an array x times for each dimension For $iDimension = $iDimensions - 2 To 0 Step -1 Local $sArrayParent = "[" $sArrayParent &= $sArray For $y = 0 To UBound($array, $iDimension + 1)-2 $sArrayParent &= "," & $sArray Next $sArray = $sArrayParent & "]" Next Return $sArray EndIf Next Local $sJson = "" While 1 For $iDimension = $iDimensions - 1 To 0 Step -1 If $aIndices[$iDimension] = 0 Then $sJson &= "[" ContinueLoop EndIf ExitLoop Next $sPosition = StringFormat('[%s]', _ArrayToString($aIndices, '][', 0, $iDimensions-1)) $sJson &= __json_encode(Execute('$array'&$sPosition), $fnReplacer) If $aIndices[$iDimensions -1 ] < UBound($array, $iDimensions) - 1 Then $sJson &= "," EndIf For $iDimension = $iDimensions - 1 To 0 Step -1 $aIndices[$iDimension] += 1 If $aIndices[$iDimension] <= UBound($array, $iDimension + 1)-1 Then ; Current dimension index is not the last element, so we stop regrouping and exit the loop ExitLoop EndIf $sJson &= "]" If $iDimension = 0 Then ExitLoop 2 If $aIndices[$iDimension - 1] < UBound($array, $iDimension) - 1 Then ; Parent index position is not the last element, so we add a comma, to accommodate the next sibling element $sJson &= "," EndIf ; Reset the index positon of the current dimension $aIndices[$iDimension] = 0 Next WEnd Return $sJson EndFunc Func __json_encode_string(ByRef $s) Return '"' & StringRegExpReplace($s, '["\\]', '\\$0') & '"' EndFunc Func __json_encode_number(ByRef $n) Return String($n) EndFunc Func __json_encode_bool(ByRef $b) Return $b ? "true" : "false" EndFunc Func __json_encode_null(ByRef $n) Return "null" EndFunc Func _json_encode_pretty($vJson, $sIndentation = 4, $fnReplacer = Null) If (Not IsInt($sIndentation)) And (Not IsString($sIndentation)) Then $sIndentation = " " If IsInt($sIndentation) Then $sIndentation = _StringRepeat(" ", $sIndentation) If Not IsFunc($fnReplacer) Then $fnReplacer = Null Return __json_encode_pretty($vJson, 0, $sIndentation, $fnReplacer) EndFunc Func __json_encode_pretty(ByRef $v, $iLevel, $sIndentation, $fnReplacer) Switch VarGetType($v) Case "Map" Return __json_encode_map_pretty($v, $iLevel, $sIndentation, $fnReplacer) Case "Array" Return __json_encode_array_pretty($v, $iLevel, $sIndentation, $fnReplacer) Case "String" Return __json_encode_string($v) Case "Int32" ContinueCase Case "Int64" ContinueCase Case "Double" Return __json_encode_number($v) Case "Bool" Return __json_encode_bool($v) Case "Keyword" If Not ($v = Null) Then ContinueCase Return __json_encode_null($v) Case Else If IsFunc($fnReplacer) Then Return __json_encode_pretty(Call($fnReplacer, $v), $iLevel, $sIndentation, Null) Return __json_encode_null($v) EndSwitch EndFunc Func __json_encode_map_pretty(ByRef $map, $iLevel, $sIndentation, $fnReplacer) if UBound($map) = 0 Then Return "{}" Local $aKeys = MapKeys($map) Local $indentString = _StringRepeat($sIndentation, $iLevel) Local $nextIndentString = UBound($aKeys) > 0 ? _StringRepeat($sIndentation, $iLevel + 1) : "" Local $sJson = "{" For $key In $aKeys $sJson &= @LF & $nextIndentString & __json_encode_string($key) & ": " & __json_encode_pretty($map[$key], $iLevel + 1, $sIndentation, $fnReplacer) & "," IF @error <> 0 Then Return SetError(@error, @extended, Null) Next If UBound($aKeys) > 0 Then $sJson = StringMid($sJson, 1, StringLen($sJson) - 1) & @LF & $indentString Return $sJson & "}" EndFunc Func __json_encode_array_pretty(ByRef $array, $iLevel, $sIndentation, $fnReplacer) Local $iDimensions = UBound($array, 0) Local $aIndices[$iDimensions] For $iIndex = 0 To $iDimensions - 1 $aIndices[$iIndex] = 0; Fill array with 0 If UBound($array, $iIndex + 1) = 0 Then; Special handling for array dimention with length 0 Redim $aIndices[$iIndex+1]; Resize array dimentions to first occurence of length zero, as no child elements can exist $iDimensions = $iIndex + 1 Local $sArray = "[]" ; The loop will wrap the child element(s) in an array x times for each dimension For $iDimension = $iDimensions - 2 To 0 Step -1 Local $sArrayParent = _StringRepeat($sIndentation, $iLevel + $iDimension - 1) & "[" & @LF & _StringRepeat($sIndentation, $iLevel + $iDimension + 1) $sArrayParent &= $sArray For $y = 0 To UBound($array, $iDimension + 1)-2 $sArrayParent &= "," & @LF & _StringRepeat($sIndentation, $iLevel + $iDimension + 1) & $sArray Next $sArray = $sArrayParent & @LF & _StringRepeat($sIndentation, $iLevel + $iDimension) & "]" Next Return $sArray EndIf Next Local $sJson = "", $_iLevel = $iLevel While 1 For $iDimension = $iDimensions - 1 To 0 Step -1 If $aIndices[$iDimension] = 0 Then If $iDimension > 0 Or $iDimensions > 1 Then $sJson &= _StringRepeat($sIndentation, $_iLevel) $sJson &= "[" & @LF $_iLevel += 1 ContinueLoop EndIf ExitLoop Next $sPosition = StringFormat('[%s]', _ArrayToString($aIndices, '][', 0, $iDimensions-1)) $sJson &= _StringRepeat($sIndentation, $_iLevel) & __json_encode_pretty(Execute('$array'&$sPosition), $_iLevel, $sIndentation, $fnReplacer) If $aIndices[$iDimensions -1 ] < UBound($array, $iDimensions) - 1 Then $sJson &= "," EndIf $sJson &= @LF For $iDimension = $iDimensions - 1 To 0 Step -1 $aIndices[$iDimension] += 1 If $aIndices[$iDimension] <= UBound($array, $iDimension + 1)-1 Then ; Current dimension index is not the last element, so we stop regrouping and exit the loop ExitLoop EndIf $_iLevel -= 1 $sJson &= _StringRepeat($sIndentation, $_iLevel) & "]" If $iDimension = 0 Then ExitLoop 2 If $aIndices[$iDimension - 1] < UBound($array, $iDimension) - 1 Then ; Parent index position is not the last element, so we add a comma, to accommodate the next sibling element $sJson &= "," EndIf $sJson &= @LF ; Reset the index positon of the current dimension $aIndices[$iDimension] = 0 Next WEnd Return $sJson EndFunc Func Json_StringEncode($sString, $iOption = 0) $sString = StringReplace($sString, "\", "\\") $sString = StringReplace($sString, '"', '\"') $sString = StringReplace($sString, @CRLF, "\n") $sString = StringReplace($sString, @LF, "\n") $sString = StringReplace($sString, @TAB, "\t") $sString = StringReplace($sString, Chr(8), "\b") $sString = StringReplace($sString, Chr(12), "\f") Return '"' & $sString & '"' EndFunc Func Json_Parse($sJson) Local $oResult = _JSON_Parse($sJson) If @error Then MsgBox(16, "Error", "Failed to parse JSON") Return SetError(1, 0, 0) EndIf Return $oResult EndFunc ;Func Json_Parse($sJson) ; Local $oScript = ObjCreate("MSScriptControl.ScriptControl") ; If Not IsObj($oScript) Then ; MsgBox(16, "Error", "MSScriptControl is not available. Try running in 32-bit AutoIt.") ; Return SetError(1, 0, 0) ; EndIf; ; $oScript.Language = "JScript" ; Local $sCode = _ ; "function parse(json) {" & _ ; " return JSON.parse(json);" & _ ; "}" ; $oScript.AddCode($sCode) ; Local $oResult = $oScript.Run("parse", $sJson) ; Return $oResult ;EndFunc Func Json_Decode($sJson) Return Json_Parse($sJson) EndFunc Func Json_Put(ByRef $oJson, $sKey, $vValue) If IsObj($oJson) Then $oJson.Item($sKey) = $vValue Return 1 Else SetError(1) Return 0 EndIf EndFunc #include-once ; #INDEX# ======================================================================================================================= ; Title .........: JSON-UDF ; Version .......: 0.10 ; AutoIt Version : 3.3.16.1 ; Language ......: english (german maybe by accident) ; Description ...: Function for interacting with JSON data in AutoIt. ; This includes import, export as well as helper functions for handling nested AutoIt data structures. ; Author(s) .....: AspirinJunkie, Sven Seyfert (SOLVE-SMART) ; Last changed ..: 2023-04-29 ; Link ..........: https://autoit.de/thread/85435-json-udf/ ; License .......: This work is free. ; You can redistribute it and/or modify it under the terms of the Do What The Fuck You Want To Public License, Version 2, ; as published by Sam Hocevar. ; See http://www.wtfpl.net/ for more details. ; =============================================================================================================================== ; #Function list# ======================================================================================================================= ; ---- import and export from or to json ------ ; _JSON_Parse - converts a JSON-structured string into a nested AutoIt data structure ; _JSON_Generate - converts a nested AutoIt data structure into a JSON structured string ; _JSON_GenerateCompact - shorthand for _JSON_Generate() to create JSON structured strings as compact as possible ; _JSON_Unminify - reads minified (compact) JSON file or string and converts to well readable JSON string ; _JSON_Minify - reads unminified (readable) JSON file or string and converts to minified (compact) JSON string ; ; ---- extraction and manipulation of nested AutoIt data structures ---- ; _JSON_Get - extract query nested AutoIt-datastructure with a simple selector string ; _JSON_addChangeDelete - create a nested AutoIt data structure, change values within existing structures or delete elements from a nested AutoIt data structure ; ; ---- helper functions ---- ; __JSON_FormatString - converts a string into a json string by escaping the special symbols ; __JSON_ParseString - converts a json formatted string into an AutoIt-string by unescaping the json-escapes ; __JSON_A2DToAinA - converts a 2D array into a Arrays in Array ; __JSON_AinAToA2d - converts a Arrays in Array into a 2D array ; __JSON_Base64Decode - decode data which is coded as a base64-string into binary variable ; __JSON_Base64Encode - converts a binary- or string-Input into BASE64 (or optional base64url) format ; =============================================================================================================================== #include ; #FUNCTION# ====================================================================================== ; Name ..........: _JSON_Parse ; Description ...: convert a JSON-formatted string into a nested structure of AutoIt-datatypes ; Syntax ........: _JSON_Parse(Const $s_String, $i_Os = 1) ; Parameters ....: $s_String - a string formatted as JSON ; [$i_Os] - search position where to start (normally don't touch!) ; Return values .: Success - Return a nested structure of AutoIt-datatypes ; @extended = next string offset ; Failure - Return "" and set @error to: ; @error = 1 - part is not json-syntax ; = 2 - key name in object part is not json-syntax ; = 3 - value in object is not correct json ; = 4 - delimiter or object end expected but not gained ; Author ........: AspirinJunkie ; ================================================================================================= Func _JSON_Parse(Const $s_String, $i_Os = 1) Local $i_OsC = $i_Os, $o_Current, $o_Value ; Inside a character class, \R is treated as an unrecognized escape sequence, and so matches the letter "R" by default, but causes an error if Local Static _ ; '\s' = [\x20\x09\x0A\x0D] $s_RE_G_String = '\G\s*"([^"\\]*+(?>\\.[^"\\]*+)*+)"', _ ; old variant: '\G\s*"((?>[^\\"]+|\\.)*+)"' - new one is more efficient coz it searches firstly for non quotes and bs - these are more unlikely $s_RE_G_Number = '\G\s*(-?(?>0|[1-9]\d*)(?>\.\d+)?(?>[eE][-+]?\d+)?)', _ $s_RE_G_KeyWord = '\G\s*\b(null|true|false)\b', _ $s_RE_G_Object_Begin = '\G\s*\{', _ $s_RE_G_Object_Key = '\G\s*"((?>[^\\"]+|\\.)*+)"\s*:', _ $s_RE_G_Object_Further = '\G\s*,', _ $s_RE_G_Object_End = '\G\s*\}', _ $s_RE_G_Array_Begin = '\G\s*\[', _ $s_RE_G_Array_End = '\G\s*\]' $o_Current = StringRegExp($s_String, $s_RE_G_String, 1, $i_Os) ; String If Not @error Then Return SetExtended(@extended, __JSON_ParseString($o_Current[0])) StringRegExp($s_String, $s_RE_G_Object_Begin, 1, $i_Os) ; Object If Not @error Then $i_OsC = @extended Local $s_Key, $a_T Local $o_Current[] StringRegExp($s_String, $s_RE_G_Object_End, 1, $i_OsC) ; check for empty object If Not @error Then ; empty object $i_OsC = @extended Else Do $a_T = StringRegExp($s_String, $s_RE_G_Object_Key, 1, $i_OsC) ; key of element If @error Then Return SetError(2, $i_OsC, "") $i_OsC = @extended $s_Key = __JSON_ParseString($a_T[0]) $o_Value = _JSON_Parse($s_String, $i_OsC) If @error Then Return SetError(3, $i_OsC, "") $i_OsC = @extended $o_Current[$s_Key] = $o_Value ; add key:value to map StringRegExp($s_String, $s_RE_G_Object_Further, 1, $i_OsC) ; more elements If Not @error Then $i_OsC = @extended ContinueLoop Else StringRegExp($s_String, $s_RE_G_Object_End, 1, $i_OsC) ; end of array If Not @error Then $i_OsC = @extended ExitLoop Else Return SetError(4, $i_OsC, "") EndIf EndIf Until False EndIf Return SetExtended($i_OsC, $o_Current) EndIf StringRegExp($s_String, $s_RE_G_Array_Begin, 1, $i_Os) ; Array If Not @error Then $i_OsC = @extended Local $o_Current[1], $d_N = 1, $i_C = 0 StringRegExp($s_String, $s_RE_G_Array_End, 1, $i_OsC) ; check for empty array If Not @error Then ; empty array ReDim $o_Current[0] $i_OsC = @extended Return SetExtended($i_OsC, $o_Current) EndIf Do $o_Value = _JSON_Parse($s_String, $i_OsC) If @error Then Return SetError(3, $i_OsC, "") $i_OsC = @extended If $i_C = $d_N - 1 Then $d_N += $d_N ; or *= 2 ReDim $o_Current[$d_N] EndIf $o_Current[$i_C] = $o_Value $i_C += 1 StringRegExp($s_String, $s_RE_G_Object_Further, 1, $i_OsC) ; more elements If Not @error Then $i_OsC = @extended ContinueLoop Else StringRegExp($s_String, $s_RE_G_Array_End, 1, $i_OsC) ; end of array If Not @error Then $i_OsC = @extended ExitLoop Else Return SetError(5, $i_OsC, "") EndIf EndIf Until False If UBound($o_Current) <> $i_C Then ReDim $o_Current[$i_C] Return SetExtended($i_OsC, $o_Current) EndIf $o_Current = StringRegExp($s_String, $s_RE_G_Number, 1, $i_Os) ; Number If Not @error Then Return SetExtended(@extended, Number($o_Current[0])) $o_Current = StringRegExp($s_String, $s_RE_G_KeyWord, 1, $i_Os) ; KeyWord If Not @error Then Return SetExtended(@extended, Execute($o_Current[0])) ; $o_Current[0] = "null" ? Null : $o_Current[0] = "true" ? True : False) Return SetError(1, $i_OsC, "") EndFunc ;==>_JSON_Parse ; #FUNCTION# ====================================================================================== ; Name ..........: _JSON_Generate ; Description ...: converts a nested AutoIt data structure into a JSON structured string ; Syntax ........: _JSON_Generate($o_Object, $s_ObjIndent = @TAB, $s_ObjDelEl = @CRLF, $s_ObjDelKey = " ", $s_ObjDelVal = "", $s_ArrIndent = @TAB, $s_ArrDelEl = @CRLF, $i_Level = 0) ; Parameters ....: $o_Object - [nested] AutoIt data structure ; [$s_ObjIndent] - indent for object elements (only reasonable if $s_ObjDelEl contains a line skip ; [$s_ObjDelEl] - delimiter between object elements ; [$s_ObjDelKey] - delimiter between keyname and ":" in object ; [$s_ObjDelVal] - delimiter between ":" and value in object ; [$s_ArrIndent] - indent for array elements (only reasonable if $s_ArrDelEl contains a line skip) ; [$s_ArrDelEl] - delimiter between array elements ; [$i_Level] - search position where to start (normally don't touch!) ; Return values .: Success - Return a JSON formatted string ; Failure - Return "" ; Author ........: AspirinJunkie ; ================================================================================================= Func _JSON_Generate($o_Object, $s_ObjIndent = @TAB, $s_ObjDelEl = @CRLF, $s_ObjDelKey = "", $s_ObjDelVal = " ", $s_ArrIndent = @TAB, $s_ArrDelEl = @CRLF, $i_Level = 0) Local Static $s_JSON_String If $i_Level = 0 Then $s_JSON_String = "" Switch VarGetType($o_Object) Case "String" $s_JSON_String &= '"' & __JSON_FormatString($o_Object) & '"' Case "Int32", "Int64", "Float", "Double" $s_JSON_String &= String($o_Object) Case "Bool" $s_JSON_String &= StringLower($o_Object) Case "Keyword" If IsKeyword($o_Object) = 2 Then $s_JSON_String &= "null" Case "Binary" $s_JSON_String &= '"' & __JSON_Base64Encode($o_Object) & '"' Case "Array" If UBound($o_Object, 0) = 2 Then $o_Object = __JSON_A2DToAinA($o_Object) If UBound($o_Object) = 0 Then $s_JSON_String &= "[]" Else $s_JSON_String &= "[" & $s_ArrDelEl For $o_Value In $o_Object $s_JSON_String &= _StringRepeat($s_ArrIndent, $i_Level + 1) _JSON_Generate($o_Value, $s_ObjIndent, $s_ObjDelEl, $s_ObjDelKey, $s_ObjDelVal, $s_ArrIndent, $s_ArrDelEl, $i_Level + 1) $s_JSON_String &= "," & $s_ArrDelEl Next $s_JSON_String = StringTrimRight($s_JSON_String, StringLen("," & $s_ArrDelEl)) & $s_ArrDelEl & _StringRepeat($s_ArrIndent, $i_Level) & "]" EndIf Case "Object" If ObjName($o_Object) = "Dictionary" Then Local $s_KeyTemp, $o_Value If $o_Object.Count() = 0 Then $s_JSON_String &= "{}" Else $s_JSON_String &= "{" & $s_ObjDelEl For $s_Key In $o_Object.Keys $s_KeyTemp = $s_Key $o_Value = $o_Object($s_Key) $s_JSON_String &= _StringRepeat($s_ObjIndent, $i_Level + 1) & '"' & __JSON_FormatString($s_KeyTemp) & '"' & $s_ObjDelKey & ':' & $s_ObjDelVal _JSON_Generate($o_Value, $s_ObjIndent, $s_ObjDelEl, $s_ObjDelKey, $s_ObjDelVal, $s_ArrIndent, $s_ArrDelEl, $i_Level + 1) $s_JSON_String &= "," & $s_ObjDelEl Next $s_JSON_String = StringTrimRight($s_JSON_String, StringLen("," & $s_ObjDelEl)) & $s_ObjDelEl & _StringRepeat($s_ObjIndent, $i_Level) & "}" EndIf EndIf Case "Map" Local $s_KeyTemp, $o_Value If UBound($o_Object) = 0 Then $s_JSON_String &= "{}" Else $s_JSON_String &= "{" & $s_ObjDelEl For $s_Key In MapKeys($o_Object) $s_KeyTemp = $s_Key $o_Value = $o_Object[$s_Key] $s_JSON_String &= _StringRepeat($s_ObjIndent, $i_Level + 1) & '"' & __JSON_FormatString($s_KeyTemp) & '"' & $s_ObjDelKey & ':' & $s_ObjDelVal _JSON_Generate($o_Value, $s_ObjIndent, $s_ObjDelEl, $s_ObjDelKey, $s_ObjDelVal, $s_ArrIndent, $s_ArrDelEl, $i_Level + 1) $s_JSON_String &= "," & $s_ObjDelEl Next $s_JSON_String = StringTrimRight($s_JSON_String, StringLen("," & $s_ObjDelEl)) & $s_ObjDelEl & _StringRepeat($s_ObjIndent, $i_Level) & "}" EndIf Case "Ptr" $s_JSON_String &= String(Int($o_Object)) Case "DLLStruct" Local $tBin = DllStructCreate("Byte[" & DllStructGetSize($o_Object) & "]", DllStructGetPtr($o_Object)) $s_JSON_String &= '"' & __JSON_Base64Encode(DllStructGetData($tBin, 1)) & '"' EndSwitch If $i_Level = 0 Then Local $s_Temp = $s_JSON_String $s_JSON_String = "" Return $s_Temp EndIf EndFunc ;==>_JSON_Generate ; #FUNCTION# ==================================================================================================================== ; Name ..........: _JSON_GenerateCompact ; Description ...: shorthand for _JSON_Generate()-parameters to produce a compact as possible JSON string ; Syntax ........: _JSON_GenerateCompact($o_Object) ; Parameters ....: $o_Object - [nested] AutoIt data structure ; Return values .: Success - Return a JSON formatted string ; Failure - Return "" ; Author ........: AspirinJunkie ; Modified ......: 2023-05-23 ; Related .......: _JSON_Generate ; =============================================================================================================================== Func _JSON_GenerateCompact($o_Object) Return _JSON_Generate($o_Object, "", "", "", "", "", "") EndFunc ;==>_JSON_GenerateCompact ; #FUNCTION# ==================================================================================================================== ; Name ..........: _JSON_Unminify ; Description ...: reads minified (compact) JSON file or string and converts to well readable JSON string ; Syntax ........: _JSON_Unminify($s_Input) ; Parameters ....: $s_Input - json file path/handle or json string ; Return values .: Success - Return a JSON formatted string ; Failure - Return "" and set @error to: ; @error = 1 - error during FileRead() - @extended = @error from FileRead() ; = 2 - no valid format for $s_Input ; Author ........: Sven Seyfert (SOLVE-SMART), AspirinJunkie ; Related .......: _JSON_Generate ; =============================================================================================================================== Func _JSON_Unminify($s_Input) ; read file if $sInput = file name or file handle If FileExists($s_Input) Or IsInt($s_Input) Then $s_Input = FileRead($s_Input) If @error Then Return SetError(1, @error, False) If Not IsString($s_Input) Then Return SetError(2, 0, False) Local Const $o_Object = _JSON_Parse($s_Input) Return _JSON_Generate($o_Object) EndFunc ;==>_JSON_Unminify ; #FUNCTION# ==================================================================================================================== ; Name ..........: _JSON_Minify ; Description ...: reads unminified (readable) JSON file or string and converts to minified (compact) JSON string ; Syntax ........: _JSON_Minify($s_Input) ; Parameters ....: $s_Input - json file path/handle or json string ; Return values .: Success - Return a JSON formatted string ; Failure - Return "" and set @error to: ; @error = 1 - error during FileRead() - @extended = @error from FileRead() ; = 2 - no valid format for $s_Input ; Author ........: Sven Seyfert (SOLVE-SMART), AspirinJunkie ; Related .......: _JSON_GenerateCompact ; =============================================================================================================================== Func _JSON_Minify($s_Input) ; read file if $sInput = file name or file handle If FileExists($s_Input) Or IsInt($s_Input) Then $s_Input = FileRead($s_Input) If @error Then Return SetError(1, @error, False) If Not IsString($s_Input) Then Return SetError(2, 0, False) Local Const $o_Object = _JSON_Parse($s_Input) Return _JSON_GenerateCompact($o_Object) EndFunc ;==>_JSON_Minify ; #FUNCTION# ====================================================================================== ; Name ..........: _JSON_Get ; Description ...: query nested AutoIt-datastructure with a simple query string with syntax: ; MapKey#1.MapKey#2.[ArrayIndex#1].MapKey#3... (points keynames can be achieved by "\.") ; multidimensional (2D or 3D only) array indices are separated through comma - e.g.: [2,3] ; Syntax ........: _JSON_Get(ByRef $o_Object, Const $s_Pattern) ; Parameters ....: $o_Object - a nested AutoIt datastructure (Arrays, Dictionaries, basic scalar types) ; $s_Pattern - query pattern like described above ; Return values .: Success - Return the queried object out of the nested datastructure ; Failure - Return "" and set @error to: ; @error = 1 - pattern is not correct ; = 2 - keyname query to none dictionary object ; = 3 - keyname queried not exists in dictionary ; = 4 - index query on none array object ; = 5 - index out of array range ; = 6 - number of subindices in index query not match array dimensions ; = 7 - more than 3 array dimensions are not supported ; Author ........: AspirinJunkie ; ================================================================================================= Func _JSON_Get(ByRef $o_Object, Const $s_Pattern) Local $o_Current = $o_Object, $d_Val Local $a_Tokens = StringRegExp($s_Pattern, '\[(\d+|[\d\h,]+)\]|((?>\\.|[^\.\[\]\\]+)+)', 4) If @error Then Return SetError(1, @error, "") For $a_CurToken In $a_Tokens If UBound($a_CurToken) = 3 Then ; KeyName $a_CurToken[2] = StringRegExpReplace($a_CurToken[2], '\\(.)', '$1') Switch VarGetType($o_Current) Case "Object" If Not IsObj($o_Current) Or ObjName($o_Current) <> "Dictionary" Then Return SetError(2, 0, "") If Not $o_Current.Exists($a_CurToken[2]) Then Return SetError(3, 0, "") $o_Current = $o_Current($a_CurToken[2]) Case "Map" If Not MapExists($o_Current, $a_CurToken[2]) Then Return SetError(3, 0, "") $o_Current = $o_Current[$a_CurToken[2]] EndSwitch ElseIf UBound($a_CurToken) = 2 Then ; ArrayIndex If (Not IsArray($o_Current)) Then Return SetError(4, UBound($o_Current, 0), "") ; multi dimensional array If StringInStr($a_CurToken[1], ',', 1) Then Local $aIndices = StringSplit($a_CurToken[1], ',', 3) If UBound($aIndices) <> UBound($o_Current, 0) Then Return SetError(6, UBound($o_Current, 0), "") ; get the indices and check their range Local $x = Int($aIndices[0]), $y = Int($aIndices[1]) If $x < 0 Or $x >= UBound($o_Current, 1) Then Return SetError(5, $x, "") If $y < 0 Or $y >= UBound($o_Current, 2) Then Return SetError(5, $y, "") Switch UBound($aIndices) Case 2 ; 2D array $o_Current = $o_Current[$x][$y] Case 3 ; 3D array Local $z = Int($aIndices[2]) If $z < 0 Or $z >= UBound($o_Current, 3) Then Return SetError(5, $z, "") $o_Current = $o_Current[$x][$y][$z] Case Else Return SetError(7, @error, "") EndSwitch ; 1D array Else If UBound($o_Current, 0) <> 1 Then Return SetError(6, UBound($o_Current, 0), "") $d_Val = Int($a_CurToken[1]) If $d_Val < 0 Or $d_Val >= UBound($o_Current) Then Return SetError(5, $d_Val, "") $o_Current = $o_Current[$d_Val] EndIf EndIf Next Return $o_Current EndFunc ;==>_JSON_Get ; #FUNCTION# ====================================================================================== ; Name ..........: _JSON_addChangeDelete ; Description ...: creates, modifies or deletes within nested AutoIt structures with a simple query string with syntax: ; MapKey#1.MapKey#2.[ArrayIndex#1].MapKey#3... (points keynames can be achieved by "\.") ; If the specified structure already exists, then the function overwrite the existing data. ; If the specified structure not exists, then the functions creates this structure. ; If $vVal = Default, then the function deletes this specific data point inside the structure. ; Syntax ........: _JSON_addChangeDelete(ByRef $oObject, Const $sPattern, Const $vVal = Default [, Const $iRecLevel = 0]) ; Parameters ....: $oObject - a nested AutoIt datastructure (Arrays, Maps, basic scalar types etc.) ; in which the structure is to be created or data is to be changed or deleted ; $sPattern - query pattern like described above ; $vVal - the value which should be written at the position in $sPattern ; - if $vVal = Default then the position in $sPattern is to be deleted ; $iRecLevel - don't touch! - only for internal purposes ; Return values .: Success - Return True ; Failure - Return False and set @error to: ; @error = 1 - pattern is not correct ; @error = 2 - wrong index for array element ; Author ........: AspirinJunkie ; ================================================================================================= Func _JSON_addChangeDelete(ByRef $oObject, Const $sPattern, Const $vVal = Default, Const $iRecLevel = 0) Local Static $aLevels[0] ; only on highest recursion level: process the selector string If $iRecLevel = 0 Then Local $aToken = StringRegExp($sPattern, '\[(\d+)\]|((?>\\.|[^\.\[\]\\]+)+)', 4) If @error Then Return SetError(1, @error, "") Local $aCurToken ReDim $aLevels[UBound($aToken) + 1][2] For $i = 0 To UBound($aToken) - 1 $aCurToken = $aToken[$i] If UBound($aCurToken) = 3 Then ; KeyName $aLevels[$i][0] = "Map" $aLevels[$i][1] = StringRegExpReplace($aCurToken[2], '\\(.)', '$1') Else ; Array Index $aLevels[$i][0] = "Array" $aLevels[$i][1] = Int($aCurToken[1]) EndIf Next $aLevels[UBound($aLevels) - 1][0] = "end" EndIf ; If data structure not exists already - build it as stated in the selector string: Local $sCurrenttype = $aLevels[$iRecLevel][0] If $sCurrenttype <> VarGetType($oObject) Then Switch $sCurrenttype Case "Map" Local $mTmp[] $oObject = $mTmp Case "Array" Local $aTmp[$aLevels[$iRecLevel][1] + 1] $oObject = $aTmp Case "end" Return $vVal EndSwitch EndIf ; special case treatment for arrays If $sCurrenttype = "Array" Then If UBound($oObject, 0) <> 1 Then Local $aTmp[$aLevels[$iRecLevel][1] + 1] $oObject = $aTmp ElseIf UBound($oObject) < ($aLevels[$iRecLevel][1] + 1) Then ReDim $oObject[$aLevels[$iRecLevel][1] + 1] EndIf EndIf ; create or change the objects in the next hierarchical level and use these as value for the current entry Local $vTmp = $oObject[$aLevels[$iRecLevel][1]], _ $oNext = _JSON_addChangeDelete($vTmp, $sPattern, $vVal, $iRecLevel + 1) If $oNext = Default Then ; delete the current level Switch $sCurrenttype Case "Map" MapRemove($oObject, $aLevels[$iRecLevel][1]) Case "Array" Local $iInd = $aLevels[$iRecLevel][1], $nElems = UBound($oObject) If $iInd < 0 Or $iInd >= $nElems Then Return SetError(2, @error, "") For $i = $iInd To $nElems - 2 $oObject[$i] = $oObject[$i + 1] Next ReDim $oObject[$nElems - 1] Case Else $oObject[$aLevels[$iRecLevel][1]] = "" For $j = UBound($oObject) - 1 To 0 Step -1 If $oObject[$j] <> "" Then ReDim $oObject[$j + 1] ExitLoop EndIf Next EndSwitch Else $oObject[$aLevels[$iRecLevel][1]] = $oNext EndIf If $iRecLevel > 0 Then Return $oObject Else ReDim $aLevels[0] ; clean Return True EndIf EndFunc ;==>_JSON_addChangeDelete ; helper function for converting a json formatted string into an AutoIt-string ; slower variant of __JSON_ParseString but also can handle large strings Func __JSON_ParseString(ByRef $s_String) Local $aB[5] Local $a_RE = StringRegExp($s_String, '\\\\(*SKIP)(*FAIL)|(\\["bf/]|\\u[[:xdigit:]]{4})', 3) If Not @error Then For $s_Esc In $a_RE Switch StringMid($s_Esc, 2, 1) Case "b" If $aB[0] Then ContinueLoop $s_String = StringRegExpReplace($s_String, '\\\\(*SKIP)(*FAIL)|\\b', Chr(8)) $aB[0] = True Case "f" If $aB[1] Then ContinueLoop $s_String = StringRegExpReplace($s_String, '\\\\(*SKIP)(*FAIL)|\\f', Chr(12)) $aB[1] = True Case "/" If $aB[2] Then ContinueLoop $s_String = StringRegExpReplace($s_String, '\\\\(*SKIP)(*FAIL)|\\/', "/") $aB[2] = True Case '"' If $aB[3] Then ContinueLoop $s_String = StringRegExpReplace($s_String, '\\\\(*SKIP)(*FAIL)|\\"', '"') $aB[3] = True Case "u" If $aB[4] Then ContinueLoop $a_RE = StringRegExp($s_String, '\\\\(*SKIP)(*FAIL)|\\u\K[[:xdigit:]]{4}', 3) If Not @error Then If UBound($a_RE) > 10 Then Local $mCodes[] For $s_Code In $a_RE If MapExists($mCodes, $s_Code) Then ContinueLoop $s_String = StringReplace($s_String, "\u" & $s_Code, ChrW(Dec($s_Code)), 0, 1) $mCodes[$s_Code] = "" Next Else For $s_Code In $a_RE $s_String = StringReplace($s_String, "\u" & $s_Code, ChrW(Dec($s_Code)), 0, 1) Next EndIf $aB[4] = True EndIf EndSwitch Next EndIf ; converts \n \r \t \\ implicit: Return StringFormat(StringReplace($s_String, "%", "%%", 0, 1)) EndFunc ;==>__JSON_ParseString ; helper function for converting a AutoIt-string into a json formatted string Func __JSON_FormatString(ByRef $sString) Return StringLen($sString) < 50 ? _ StringTrimRight(StringRegExpReplace($sString & '\\\b\f\n\r\t\"', '(?s)(?|\\(?=.*(\\\\))|[\b](?=.*(\\b))|\f(?=.*(\\f))|\r\n(?=.*(\\n))|\n(?=.*(\\n))|\r(?=.*(\\r))|\t(?=.*(\\t))|"(?=.*(\\")))', '\1'), 15) : _ StringReplace( _ StringReplace( _ StringReplace( _ StringReplace( _ StringReplace( _ StringReplace( _ StringReplace( _ StringReplace($sString, '\', '\\', 0, 1) _ , Chr(8), "\b", 0, 1) _ , Chr(12), "\f", 0, 1) _ , @CRLF, "\n", 0, 1) _ , @LF, "\n", 0, 1) _ , @CR, "\r", 0, 1) _ , @TAB, "\t", 0, 1) _ , '"', '\"', 0, 1) EndFunc ; #FUNCTION# ====================================================================================== ; Name ..........: __JSON_Base64Encode ; Description ...: convert a binary- or string-Input into BASE64 (or optional base64url) format ; mainly a wrapper for the CryptBinaryToString API-function ; Syntax ........: __JSON_Base64Encode(Const ByRef $s_Input, [Const $b_base64url = False]) ; Parameters ....: $s_Input - binary data or string which should be converted ; [$b_base64url] - If true the output is in base64url-format instead of base64 ; Return values .: Success - Return base64 (or base64url) formatted string ; Failure - Return "" and set @error to: ; @error = 1 - failure at the first run to calculate the output size ; = 2 - failure at the second run to calculate the output ; Author ........: AspirinJunkie ; Example .......: Yes ; $s_Base64String = __JSON_Base64Encode("This is my test") ; ================================================================================================= Func __JSON_Base64Encode(Const ByRef $s_Input, Const $b_base64url = False) Local $b_Input = IsBinary($s_Input) ? $s_Input : Binary($s_Input) Local $t_BinArray = DllStructCreate("BYTE[" & BinaryLen($s_Input) & "]") DllStructSetData($t_BinArray, 1, $b_Input) Local $h_DLL_Crypt32 = DllOpen("Crypt32.dll") ; first run to calculate needed size of output buffer Local $a_Ret = DllCall($h_DLL_Crypt32, "BOOLEAN", "CryptBinaryToString", _ "STRUCT*", $t_BinArray, _ ; *pbBinary "DWORD", DllStructGetSize($t_BinArray), _ ; cbBinary "DWORD", 0x40000001, _ ; dwFlags "PTR", Null, _ ; pszString "DWORD*", 0) If @error Or Not IsArray($a_Ret) Or $a_Ret[0] = 0 Then Return SetError(1, @error, DllClose($h_DLL_Crypt32)) ; second run to calculate base64-string: Local $t_Output = DllStructCreate("CHAR Out[" & $a_Ret[5] & "]") Local $a_Ret2 = DllCall($h_DLL_Crypt32, "BOOLEAN", "CryptBinaryToString", _ "STRUCT*", $t_BinArray, _ ; *pbBinary "DWORD", DllStructGetSize($t_BinArray), _ ; cbBinary "DWORD", 0x40000001, _ ; dwFlags "STRUCT*", $t_Output, _ ; pszString "DWORD*", $a_Ret[5]) If @error Or Not IsArray($a_Ret2) Or $a_Ret2[0] = 0 Then Return SetError(2, @error, DllClose($h_DLL_Crypt32)) Local $s_Output = $t_Output.Out If StringInStr($s_Output, "=", 1, 1) Then $s_Output = StringLeft($s_Output, StringInStr($s_Output, "=", 1, 1) - 1) If $b_base64url Then $s_Output = StringReplace(StringReplace($s_Output, "/", "_", 0, 1), "+", "-", 0, 1) DllClose($h_DLL_Crypt32) Return $s_Output EndFunc ;==>__JSON_Base64Encode ; #FUNCTION# ====================================================================================== ; Name ..........: __JSON_Base64Decode ; Description ...: decode data which is coded as a base64-string into binary form ; mainly a wrapper for the CryptStringToBinary API-function ; Syntax ........: __JSON_Base64Decode(Const ByRef $s_Input, [Const $b_base64url = False]) ; Parameters ....: $s_Input - string in base64-format ; [$b_base64url] - If true the output is in base64url-format instead of base64 ; Return values .: Success - Return base64 (or base64url) formatted string ; Failure - Return "" and set @error to: ; @error = 1 - failure at the first run to calculate the output size ; = 2 - failure at the second run to calculate the output ; Author ........: AspirinJunkie ; Example .......: Yes ; MsgBox(0, '', BinaryToString(__JSON_Base64Decode("VGVzdA"))) ; ================================================================================================= Func __JSON_Base64Decode(Const ByRef $s_Input, Const $b_base64url = False) Local $h_DLL_Crypt32 = DllOpen("Crypt32.dll") ; hier noch einen Reg-Ex zum testen ob String base64-codiert ist ; first run to calculate needed size of output buffer Local $a_Ret = DllCall($h_DLL_Crypt32, "BOOLEAN", "CryptStringToBinary", _ "STR", $s_Input, _ ; pszString "DWORD", 0, _ ; cchString "DWORD", 1, _ ; dwFlags "PTR", Null, _ ; pbBinary "DWORD*", 0, _ ; pcbBinary "PTR", Null, _ ; pdwSkip "PTR", Null) ; pdwFlags Local $t_Ret = DllStructCreate("BYTE Out[" & $a_Ret[5] & "]") If @error Or Not IsArray($a_Ret) Or $a_Ret[0] = 0 Then Return SetError(1, @error, DllClose($h_DLL_Crypt32)) ; second run to calculate the output data: Local $a_Ret2 = DllCall($h_DLL_Crypt32, "BOOLEAN", "CryptStringToBinary", _ "STR", $s_Input, _ ; pszString "DWORD", 0, _ ; cchString "DWORD", 1, _ ; dwFlags "STRUCT*", $t_Ret, _ ; pbBinary "DWORD*", $a_Ret[5], _ ; pcbBinary "PTR", Null, _ ; pdwSkip "PTR", Null) ; pdwFlags If @error Or Not IsArray($a_Ret2) Or $a_Ret2[0] = 0 Then Return SetError(2, @error, DllClose($h_DLL_Crypt32)) DllClose($h_DLL_Crypt32) Local $s_Output = $t_Ret.Out If $b_base64url Then $s_Output = StringReplace(StringReplace($s_Output, "_", "/", 0, 1), "-", "+", 0, 1) Return $s_Output EndFunc ;==>__JSON_Base64Decode ; #FUNCTION# ====================================================================================== ; Name ..........: __JSON_A2DToAinA() ; Description ...: Convert a 2D array into a Arrays in Array ; Syntax ........: __JSON_A2DToAinA(ByRef $A) ; Parameters ....: $A - the 2D-Array which should be converted ; Return values .: Success: a Arrays in Array build from the input array ; Failure: False ; @error = 1: $A is'nt an 2D array ; Author ........: AspirinJunkie ; ================================================================================================= Func __JSON_A2DToAinA(ByRef $A, $bTruncEmpty = True) If UBound($A, 0) <> 2 Then Return SetError(1, UBound($A, 0), False) Local $N = UBound($A), $u = UBound($A, 2) Local $a_Ret[$N] If $bTruncEmpty Then For $i = 0 To $N - 1 Local $x = $u - 1 While IsString($A[$i][$x]) And $A[$i][$x] = "" $x -= 1 WEnd Local $t[$x + 1] For $j = 0 To $x $t[$j] = $A[$i][$j] Next $a_Ret[$i] = $t Next Else For $i = 0 To $N - 1 Local $t[$u] For $j = 0 To $u - 1 $t[$j] = $A[$i][$j] Next $a_Ret[$i] = $t Next EndIf Return $a_Ret EndFunc ;==>__JSON_A2DToAinA ; #FUNCTION# ====================================================================================== ; Name ..........: __JSON_AinAToA2d() ; Description ...: Convert a Arrays in Array into a 2D array ; here useful if you want to recover 2D-arrays from a json-string ; (there exists only a array-in-array and no 2D-Arrays) ; Syntax ........: __JSON_AinAToA2d(ByRef $A) ; Parameters ....: $A - the arrays in array which should be converted ; Return values .: Success: a 2D Array build from the input array ; Failure: False ; @error = 1: $A is'nt an 1D array ; = 2: $A is empty ; = 3: first element isn't a array ; Author ........: AspirinJunkie ; ================================================================================================= Func __JSON_AinAToA2d(ByRef $A) If UBound($A, 0) <> 1 Then Return SetError(1, UBound($A, 0), False) Local $N = UBound($A) If $N < 1 Then Return SetError(2, $N, False) Local $u = UBound($A[0]) If $u < 1 Then Return SetError(3, $u, False) Local $a_Ret[$N][$u] For $i = 0 To $N - 1 Local $t = $A[$i] If UBound($t) > $u Then ReDim $a_Ret[$N][UBound($t)] For $j = 0 To UBound($t) - 1 $a_Ret[$i][$j] = $t[$j] Next Next Return $a_Ret EndFunc ;==>__JSON_AinAToA2d Func _JSON_Create() Local $oDict = ObjCreate("Scripting.Dictionary") If @error Then Return SetError(1, 0, 0) Return $oDict EndFunc