Resource icon

[VBS] JSON Klasse für Stand-Alone Scripte auf Windows

Programmiersprache(n)
VBScript
Betriebssystem(e)
Windows
Wer im Internet danach sucht, wie man per VBScript mit JSON arbeitet, findet zumeist Regex Parser und Scripting.Dictionary Workarounds. All das findet sich bei dieser Implementierung nicht. JSON ist die textuelle Repräsentation von JavaScript Objekten. Vor diesem Hintergrund habe ich versucht JavaScript Objekte und Methoden zu referenzieren und direkt in VBScript zu nutzen. Der Schlüssel dazu ist, die globalen JavaScript Objekte zu bekommen. Unter Windows stellt die MSHTML Rendering Engine "Trident" diese bereit und sie lässt sich erstaunlich einfach scripten. In eine Klasse verpackt, werden die nötigen Objekte und Funktionen bereits im Konstruktor referenziert und sind über Methodenaufrufe zugänglich. Natürlich lässt sich nicht gleichzeitig die JavaScript Syntax auf VBScript übertragen. Um validen Code zu schreiben benötigt man Wrapper, wie bspw. für den JavaScript []-Operator oder auch for-in Schleifen. Aber das sollten die Kommentare im Code näher erklären.
Die eigentliche Klasse beginnt mit Zeile 97, davor die exemplarische Nutzung.

Visual Basic:
Option Explicit

'''''''''''''''' create an instance of the custom JSON class ''''''''''''''''
Dim JSON : Set JSON = New VbsJson


'''''''''''''''' processing of example data ''''''''''''''''
' JSON string just as a literal for this example, but could have been downloaded from a web API or read from a file as well
' resulting string --> {"test": true, "int_array": [1, 2, 3], "data_object": {"key1": "one", "key2": 2.5, "key3": false}}
Const strJson = "{""test"": null, ""int_array"": [1, 2, 3], ""data_object"": {""key1"": ""one"", ""key2"": 2.5, ""key3"": false}}"
Dim jsObj, jsArr, i, strKey, strValue, strOut

' create a JavaScript object out of the JSON string
Set jsObj = JSON.Parse(strJson)

' *** 1 ***
strOut = "Single Value:" & vbNewLine
If IsNull(jsObj.test) Then ' there is no direct way to compare null (JS) with Null (VBS), use the VBScript IsNull function
  strOut = strOut & "Null" & vbNewLine
Else
  strOut = strOut & jsObj.test & vbNewLine
End If
MsgBox strOut, vbOKOnly, "*** 1 ***"

' *** 2 ***
strOut = "Integer Array:" & vbNewLine
' access the length-property of the JavaScript array for the iteration
For i = 0 To jsObj.int_array.length - 1
  ' use the wrapper method for the JavaScript [] operator to get the value of the array element with index i
  strOut = strOut & "int_array[" & i & "]" & vbTab & JSON.GetItem(jsObj.int_array, i) & vbNewLine
Next
MsgBox strOut, vbOKOnly, "*** 2 ***"

' *** 3 ***
' do the same using the ForEach method and a referenced procedure that gets index and value as arguments
Private Sub Concat1(ByRef i, ByRef v)
  strOut = strOut & "int_array[" & i & "]" & vbTab & v & vbNewLine
End Sub
strOut = "Integer Array:" & vbNewLine
JSON.ForEach jsObj.int_array, GetRef("Concat1")
MsgBox strOut, vbOKOnly, "*** 3 ***"

' *** 4 ***
strOut = "Data Object:" & vbNewLine
' get all key names as JavaScript array
Set jsArr = JSON.Keys(jsObj.data_object)
' access the length-property of the JavaScript array for the iteration
For i = 0 To jsArr.length - 1
  ' use the wrapper method for the JavaScript [] operator to get the value of the array element with index i
  strKey = JSON.GetItem(jsArr, i)
  ' use the wrapper method for the JavaScript [] operator to get the value of the object item with key strKey
  strValue = JSON.GetItem(jsObj.data_object, strKey)
  strOut = strOut & strKey & vbTab & strValue & vbNewLine
Next
MsgBox strOut, vbOKOnly, "*** 4 ***"

' *** 5 ***
' do the same using the ForEach method and a referenced procedure that gets key and value as arguments
Private Sub Concat2(ByRef k, ByRef v)
  strOut = strOut & k & vbTab & v & vbNewLine
End Sub
strOut = "Data Object:" & vbNewLine
JSON.ForEach jsObj.data_object, GetRef("Concat2")
MsgBox strOut, vbOKOnly, "*** 5 ***"

' *** 6 ***
' use the wrapper method for the JavaScript [] operator to change the value of an existing pair
JSON.SetItem jsObj.data_object, "key3", True
' use the wrapper method for the JavaScript [] operator to add a new pair with null value
JSON.SetItem jsObj.data_object, "key4", Null
' use the wrapper method for the JavaScript [] operator and the JavaScript Array constructor to add a pair with an array as value
JSON.SetItem jsObj.data_object, "key5", JSON.Array("A","B","C")
' if you want to set an object as value then use the wrapper method for the JavaScript [] operator
'  and the JavaScript Object constructor to add an empty object first ...
JSON.SetItem jsObj.data_object, "key6", JSON.Object(Null)
' ... then use the wrapper method for the JavaScript [] operator to add content
JSON.SetItem jsObj.data_object.key6, "foo", "bar"
MsgBox JSON.Stringify(jsObj.data_object, Null, 8), vbOKOnly, "*** 6 ***"

' *** 7 ***
' use the splice method of the JavaScript array to remove elements of the array
jsObj.data_object.key5.splice 2, 1 ' meaning: beginning with index 2, remove 1 element
' use the wrapper method for the JavaScript delete operator to remove an object
JSON.Delete jsObj.data_object, "key6"
MsgBox JSON.Stringify(jsObj.data_object, Null, 8), vbOKOnly, "*** 7 ***"

' *** 8 ***
' convert an ISO 8601 formatted date and time string to a VBScript local DateTime value using StrToDateTime
MsgBox JSON.StrToDateTime("2000-05-10T20:30:40.501Z"), vbOKOnly, "*** 8 ***"

' *** 9 ***
' convert a VBScript local DateTime value to an ISO 8601 formatted UTC date and time string using DateTimeToStr
MsgBox JSON.DateTimeToStr(Now), vbOKOnly, "*** 9 ***"


'''''''''''''''' custom JSON class ''''''''''''''''
Class VbsJson

  Private htmlDoc
  Public Parse, Stringify, Keys, GetItem, SetItem, Delete, DateTimeToStr, Array, Object

  ' executes a procedure for each name-value-pair if obj references an object or
  '  each index-value-pair if obj references an array
  ' the argument passed to the proc parameter needs to be a reference to a procedure
  '  with two parameters, one for the key name (object) or index (array) and one
  '  for the corresponding value
  ' the VBScript GetRef function returns the reference to be passed to proc
  Public Sub ForEach(ByRef obj, ByRef proc)
    Dim a, i, k
    Set a = Me.Keys(obj)
    For i = 0 To a.length - 1
      k = Me.GetItem(a, i)
      proc k, Me.GetItem(obj, k)
    Next
    Set a = Nothing
  End Sub

  ' convert an ISO 8601 formatted date and time string to a VBScript local DateTime value
  Public Function StrToDateTime(str)
    Dim Cast, dt
    Set Cast = htmlDoc.parentWindow.Function("str", "return new Date(str);")
    Set dt = Cast(str)
    StrToDateTime = CDate(DateSerial(dt.getFullYear(), dt.getMonth() + 1, dt.getDate()) _
                    + TimeSerial(dt.getHours(), dt.getMinutes(), dt.getSeconds() + dt.getMilliseconds() / 1000))
    Set dt = Nothing : Set Cast = Nothing
  End Function

  Private Sub Class_Initialize()
    ' HTMLFile object used to get access to specific JavaScript objects and methods of its parentWindow reference
    ' https://technet.microsoft.com/en-us/windows/aa752574(v=vs.60)
    Set htmlDoc = CreateObject("HTMLFile")
    ' the required objects and methods are supported by Internet Explorer 9 and onwards, it's mandatory to specify it
    '  in order to adjust the behavior of Trident (Microsoft HTML rendering engine) accordingly
    ' https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/compatibility/jj676915(v%3dvs.85)
    htmlDoc.open
    htmlDoc.write "<html><head><title></title><meta http-equiv=""x-ua-compatible"" content=""IE=9"" /></head></html>"
    htmlDoc.close
    ' parse method of the global JavaScript JSON object
    ' https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
    Set Me.Parse = htmlDoc.parentWindow.JSON.parse
    ' stringify method of the global JavaScript JSON object
    ' https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
    Set Me.Stringify = htmlDoc.parentWindow.JSON.stringify
    ' keys method of the global JavaScript Object object
    ' https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
    Set Me.Keys = htmlDoc.parentWindow.Object.keys
    ' use the constructor of the global JavaScript Function object to create functions that work around the [] operator
    '  in JavaScript in order to access items of arrays and objects, the delete operator to remove objects,
    '  and the toJSON method to convert DateTime values to strings
    ' https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function
    Set Me.GetItem = htmlDoc.parentWindow.Function("obj", "k", "return obj[k];")
    Set Me.SetItem = htmlDoc.parentWindow.Function("obj", "k", "val", "obj[k]=val; return;")
    Set Me.Delete = htmlDoc.parentWindow.Function("obj", "k", "delete obj[k]; return;")
    Set Me.DateTimeToStr = htmlDoc.parentWindow.Function("dt", "return (new Date(dt)).toJSON();")
    ' use the constructor of the global JavaScript Array object to create a new Array
    ' https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
    Set Me.Array = htmlDoc.parentWindow.Array
    ' use the constructor of the global JavaScript Object object to create a new object
    ' https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object
    Set Me.Object = htmlDoc.parentWindow.Object
  End Sub

  Private Sub Class_Terminate()
    Set Me.Object = Nothing : Set Me.Array = Nothing : Set Me.DateTimeToStr = Nothing: Set Me.Delete = Nothing
    Set Me.SetItem = Nothing : Set Me.GetItem = Nothing : Set Me.Keys = Nothing : Set Me.Stringify = Nothing
    Set Me.Parse = Nothing : Set htmlDoc = Nothing
  End Sub

End Class
Gefällt mir: lano
Autor
German
First release
Last update
Bewertung
0,00 Stern(e) 0 Bewertungen

More resources from German

Oben