与使用已解析的JSON对象相关的其他堆栈溢出问题的答案使用小型脚本方法,我们可以在此处使用此方法。如果说我们正在运行Microsoft
Windows版本的Excel VBA,则可以使用库中的脚本字典
Microsoft scripting Runtime。
我们可以在Javascript中创建scripting.Dictionary,使用JSON对象的键填充它,还可以使用这些值作为对子元素的引用,最后传递回VBA。在VBA中,然后可以使用Dictionary的Exists方法防御丢失的密钥。可以使用Dictionary的Count方法确定其他下游变量的尺寸。甚至可以使用Dictionary的Item方法来检索子元素(仅向下一级)。
从而,
'Tools->References->'Microsoft scripting Runtime'Microsoft script Control 1.0; {0E59F1D2-1FBE-11D0-8FF2-00A0D10038BC}; C:WindowsSysWOW64msscript.ocxOption ExplicitPrivate Function GetscriptEngine() As scriptControl Static soscriptEngine As scriptControl If soscriptEngine Is Nothing Then Set soscriptEngine = New scriptControl soscriptEngine.Language = "Jscript" soscriptEngine.AddCode "function getKeyValues(jsonObj) { " & _ " var dictionary = new ActiveXObject(""scripting.Dictionary""); " & _ " var keys = new Array(); for (var i in jsonObj) { dictionary.add(i,jsonObj[i]); }; return dictionary; } " End If Set GetscriptEngine = soscriptEngineEnd FunctionPrivate Sub TestJSONParsingWithCallByName3() Dim oscriptEngine As scriptControl Set oscriptEngine = GetscriptEngine Dim sJsonString As String sJsonString = "{'key1': 'value1' ,'key2': { 'key3': 'value3' } }" Dim objJSON As Object Set objJSON = oscriptEngine.eval("(" + sJsonString + ")") Dim dicKeys As scripting.Dictionary Set dicKeys = oscriptEngine.Run("getKeyValues", objJSON) Debug.Assert dicKeys.Count = 2 Debug.Assert TypeName(dicKeys.Item(dicKeys.Keys()(1))) = "JscriptTypeInfo" Stop If dicKeys.Exists("foobarbaz") Then '*** Next line WOULD throw "Run-time error '438': Object doesn't support this property or method" because "foobarbaz" is not a key '*** but is skipped because of defensive pre. Debug.Assert VBA.CallByName(objJSON, "foobarbaz", VbGet) End IfEnd Sub但是,我还发现了一个不需要miniscript或scripting.Dictionary的奇妙替代方法。它将允许抢占丢失的键,但没有集合类功能。它使用了hasOwnProperty()鲜为人知的属性。从而,
'Tools->References->'Microsoft script Control 1.0; {0E59F1D2-1FBE-11D0-8FF2-00A0D10038BC}; C:WindowsSysWOW64msscript.ocxOption ExplicitPrivate Sub TestJSONParsingWithCallByName4() Dim oscriptEngine As scriptControl Set oscriptEngine = New scriptControl oscriptEngine.Language = "Jscript" Dim sJsonString As String sJsonString = "{'key1': 'value1' ,'key2': { 'key3': 'value3' } }" Dim objJSON As Object Set objJSON = oscriptEngine.eval("(" + sJsonString + ")") Debug.Assert objJSON.hasOwnProperty("key1") Debug.Assert objJSON.hasOwnProperty("key2") Dim objKey2 As Object Set objKey2 = VBA.CallByName(objJSON, "key2", VbGet) Debug.Assert objKey2.hasOwnProperty("key3") If objJSON.hasOwnProperty("foobarbaz") Then '*** Next line WOULD throw "Run-time error '438': Object doesn't support this property or method" because "foobarbaz" is not a key '*** but is skipped because of defensive pre. Debug.Assert VBA.CallByName(objJSON, "foobarbaz", VbGet) End IfEnd Sub


