在Windows上的Excel VBA中,对于已解析的JSON变量,这个JScriptTypeInfo究竟是什么?

S M*_*den 4 excel vba json

在这里回答我自己的问题.
我已经在Excel VBA中使用JSON做了一些工作,并发布了许多调查结果,我将以问答形式发布这些内容 https://stackoverflow.com/help/self-answer http://blog.stackoverflow.com/2011/07/ITS-OK-到问一答,你自己的问题/

所以在stackoverflow的其他地方,人们可以看到有关在VBA中解析JSON的问题,但他们似乎错过了一两个技巧.

首先,我重新使用自定义JSON解析库,而是使用ScriptControl的Eval方法作为我所有JSON代码的基础.此外,我们还表达了本机Microsoft解决方案的偏好.

这是一个先前的问题在Windows上的Excel VBA中,如何减轻由IDE的大小写行为破坏的解析JSON的点语法遍历问题?这个问题的基础.它显示了使用VBA.CallByName比使用点语法遍历解析的JSON对象更强大.另一个先前的问题在Windows上的Excel VBA中,如何循环解析JSON数组?展示了如何使用它来访问数组元素.但是CallByName返回一个奇怪的变量类型,它在Watch窗口中显示为Object/JScriptTypeInfo,如果在一个窗口中有一个类型Debug.Print(或悬停在变量上),则会得到无信息的"[object Object]".在Windows上的Excel VBA系列中的另一个问题中,如何为已解析的JSON变量获取字符串化的JSON表示而不是"[object Object]"?我提出了一些调试"糖",可以很好地检查变量.在第四个问题中在Windows Excel VBA中,如何获取JSON键以抢占"运行时错误'438':对象不支持此属性或方法"?,在研究如何查询成员的JSON对象时,我发现似乎附加到JScriptTypeInfo对象的hasOwnProperty()方法.

所以在这个问题中我问,究竟这个JScriptTypeInfo究竟是什么?

这是5系列的问题5.这是完整系列

Q1 在Windows上的Excel VBA中,如何减轻由IDE的大小写行为破坏的解析JSON的点语法遍历问题?

Q2 在Windows上的Excel VBA中,如何循环解析JSON数组?

Q3 在Windows上的Excel VBA中,如何为已解析的JSON变量获取字符串化的JSON表示而不是"[object Object]"?

Q4 在Windows Excel VBA中,如何获取JSON键以抢占"运行时错误'438':对象不支持此属性或方法"?

Q5 在Windows上的Excel VBA中,对于已解析的JSON变量,这个JScriptTypeInfo究竟是什么?

S M*_*den 6

一个可能的地方是ScriptControl的类型库,因为这是发出此类型的库.

我机器上这种类型的完整细节是

Libary Name:    Microsoft Script Control 1.0 (Ver 1.0)       
LIBID:          {0E59F1D2-1FBE-11D0-8FF2-00A0D10038BC}
Location:       C:\wINDOWS\SysWOW64\msscript.ocx 
Run Code Online (Sandbox Code Playgroud)

使用VBA IDE的对象浏览器和反汇编类型库的OLEVIEW.exe,我无法跟踪接口JScriptTypeInfo或方法hasOwnProperty.

但是脚本引擎不是主持语言实现的情况,例如VBScript和JScript(Javascript的Microsoft名称).
所以也许我们应该寻找一个JScript实现DLL,实际上这里有一个细节

Libary Name:    Microsoft JScript Globals
LIBID:          {3EEF9759-35FC-11D1-8CE4-00C04FC2B085}
Location:       C:\wINDOWS\SysWOW64\jscript.dll 
Run Code Online (Sandbox Code Playgroud)

我的机器上没有注册,因此不在我的Tools-> References库列表或OLEVIEW.exe中.我很幸运,一边寻找一边.
这是OLEVIEW的一些输出,给出了类型库的异常

[
  uuid(3EEF9758-35FC-11D1-8CE4-00C04FC2B097)
]
dispinterface ObjectInstance {
    properties:
    methods:
        [id(0x0000044c)]
        StringInstance* toString();
        [id(0x0000044d)]
        StringInstance* toLocaleString();
        [id(0x0000044e)]
        VARIANT hasOwnProperty(VARIANT propertyName);
        [id(0x0000044f)]
        VARIANT propertyIsEnumerable(VARIANT propertyName);
        [id(0x00000450)]
        VARIANT isPrototypeOf(VARIANT obj);
        [id(0x00000451)]
        ObjectInstance* valueOf();
};
Run Code Online (Sandbox Code Playgroud)

上面显示hasOwnProperty是一个IDispatch接口(或dispinterface)的方法,它必须使用声明类型为Object的VBA对象(例如Dim foo as Object)使用regsvr32注册类型库似乎什么都不做.必须浏览到工具引用中的文件才能在VBA的对象浏览器中查看.

我们可以非常肯定这个JScript.dll文件,因为使用Process Explorer我们可以看到在执行行时加载了dll oScriptEngine.Language = "JScript" 在缺少已注册的类型库的情况下,我将文件JScript.dll加载到Notepad ++中并搜索.JScriptTypeInfo作为正则表达,发现了一个打击.答对了!

不仅有一个ObjectInstance可以描述VBA程序遇到的大多数变量,而且还有一个有趣的ArrayInstance,也许我们可以使用Javascript自己的数组函数或者至少是JScript.dll类型库中记录的子集.这是一些示例代码

'Tools->References->
'Microsoft Script Control 1.0;  {0E59F1D2-1FBE-11D0-8FF2-00A0D10038BC}; C:\Windows\SysWOW64\msscript.ocx

'and FYI/browsing capabilities       Microsoft JScript Globals;   C:\wINDOWS\SysWOW64\jscript.dll

Option Explicit

Private Sub TestJSONParsingWithCallByName5()

    Dim oScriptEngine As ScriptControl
    Set oScriptEngine = New ScriptControl
    oScriptEngine.Language = "JScript"

    Dim sJsonString(0 To 1) As String
    sJsonString(0) = "{'key1': 'value1'  ,'key2': { 'key3': 'value3' } }"
    sJsonString(1) = "[ 1234, 2345, 3456, 4567, 5678, 6789 ]"



    Dim objJSON(0 To 1) As Object
    Set objJSON(0) = oScriptEngine.Eval("(" + sJsonString(0) + ")")
    Set objJSON(1) = oScriptEngine.Eval("(" + sJsonString(1) + ")")

    Debug.Assert objJSON(0).hasOwnProperty("key1")
    Debug.Assert objJSON(0).hasOwnProperty("key2")

    Debug.Assert CallByName(objJSON(1), "length", VbGet) = 6
    Debug.Assert CallByName(objJSON(1), "0", VbGet) = "1234"

    '* Is objJSON(1) an ArrayInstance?
    '* does it support the reverse method of the ArrayInstance object?

    'Call objJSON(1).Reverse  '* reverse gets capitalised into Reverse ... grrrr
    Call CallByName(objJSON(1), "reverse", VbMethod) '* so use CallByName as solution to "helpful" capitalisation

    '* Yes, the elements are reversed!

    Debug.Assert CallByName(objJSON(1), "length", VbGet) = 6
    Debug.Assert CallByName(objJSON(1), "0", VbGet) = "6789"

    Stop

    '** And now we know objJSON(1) is an ArrayInstance we can have some fun with array operations

    Dim objSplice As Object
    Set objSplice = CallByName(objJSON(1), "splice", VbMethod, 2, 1)
    Debug.Assert CallByName(objJSON(1), "length", VbGet) = 5
    Debug.Assert CallByName(objSplice, "length", VbGet) = 1

    Dim objSlice As Object
    Set objSlice = CallByName(objJSON(1), "slice", VbMethod, 2)
    Debug.Assert CallByName(objJSON(1), "length", VbGet) = 5
    Debug.Assert CallByName(objSlice, "length", VbGet) = 3

    Stop
    Call CallByName(objJSON(1), "sort", VbMethod)


    Debug.Assert CallByName(objJSON(1), "join", VbMethod) = "1234,2345,3456,5678,6789"
    Debug.Assert CallByName(objJSON(1), "join", VbMethod, " ") = "1234 2345 3456 5678 6789"
    Stop


    Debug.Assert CallByName(objJSON(1), "pop", VbMethod) = "6789"
    Debug.Assert CallByName(objJSON(1), "length", VbGet) = 4
    Stop
End Sub
Run Code Online (Sandbox Code Playgroud)

概要:JScriptTypeInfo是在VBA IDE监视窗口中显示的东西,以及VBA函数TypeName()的返回,但它实际上隐藏了可以在JScript.dll中找到的许多对象.
我认为它可以被描述为多态,也许更好地将其描述为后期绑定.要查看功能,请使用Tools-References并浏览到JScript.dll.