首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在Windows上的Excel中,如何为解析的JSON变量获得字符串化的JSON重新表示而不是"[object Object]“?

在Windows上的Excel中,如何为解析的JSON变量获得字符串化的JSON重新表示而不是"[object Object]“?
EN

Stack Overflow用户
提问于 2016-06-08 19:17:45
回答 2查看 5.2K关注 0票数 6

在这里回答我自己的问题。

我在Excel中使用JSON做了一些工作,并发布了许多发现,我将用Q&A格式的https://stackoverflow.com/help/self-answer https://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-own-questions/这样做。

因此,在堆栈溢出的其他地方,可以看到有关在VBA中解析JSON的问题,但它们似乎遗漏了一两个技巧。

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

下面是一个先前的问题In Excel VBA on Windows, how to mitigate issue of dot syntax traversal of parsed JSON broken by IDE's capitalisation behaviour?,这个问题是建立在这个问题之上的。它展示了如何使用VBA.CallByName比使用点语法遍历解析的JSON对象更健壮。另外,前面的另一个问题In Excel VBA on Windows, how to loop through a JSON array parsed?展示了如何使用它来访问数组元素。但是CallByName返回一个奇怪的变量类型,它以Object/JScriptTypeInfo的形式出现在“监视窗口”中,如果在“立即”窗口中的一个类型(或悬停在该变量上),就会得到信息不丰富的" object“。

我们如何改进这一点,并得到一个JSON字符串表示呢?

下面是你在Debug.Print (?)之后立即看到的窗口屏幕截图。如果你悬停在一个变量上。

这是5组中的问题3,这是完整的系列

Q1 In Excel VBA on Windows, how to mitigate issue of dot syntax traversal of parsed JSON broken by IDE's capitalisation behaviour?

Q2 In Excel VBA on Windows, how to loop through a JSON array parsed?

Q3 In Excel VBA on Windows, how to get stringified JSON respresentation instead of “[object Object]” for parsed JSON variables?

Q4 In Windows Excel VBA,how to get JSON keys to pre-empt “Run-time error '438': Object doesn't support this property or method”?

Q5 In Excel VBA on Windows, for parsed JSON variables what is this JScriptTypeInfo anyway?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-06-08 19:17:45

对于与使用解析的JSON对象有关的其他堆栈溢出问题,请使用mini-script方法,我们可以在这里使用这种方法。

首先,我们承认Douglas是“javascript : The Good Parts”(http://shop.oreilly.com/product/9780596517748.do)的作者,也是javascript专家。因此,我们很高兴通过他的关于字符串化的代码。我们可以使用简单的Xml请求(通常缩写为XHR)获取他的代码,并将返回结果传递给ScriptControl的AddCode方法。然后添加一些代码,允许我们通过调用Douglas的库来覆盖"object Object“的默认表示。然后确保我们动态地将覆盖添加到所有的JScriptTypeInfo变量中,包括我们用DecodeJsonString()包装的ScriptControl的Eval方法以及用GetJSONObject()包装的VBA.CallByName产生的内容。

因此,

代码语言:javascript
运行
复制
'Tools->References->
'Microsoft Script Control 1.0;  {0E59F1D2-1FBE-11D0-8FF2-00A0D10038BC}; C:\Windows\SysWOW64\msscript.ocx
'Microsoft Xml, v6.0

Option Explicit

Private Function GetScriptEngine() As ScriptControl
    Static soScriptEngine As ScriptControl
    If soScriptEngine Is Nothing Then
        Set soScriptEngine = New ScriptControl
        soScriptEngine.Language = "JScript"

        soScriptEngine.AddCode GetJavaScriptLibrary("https://raw.githubusercontent.com/douglascrockford/JSON-js/master/json2.js")
        soScriptEngine.AddCode "function overrideToString(jsonObj) { jsonObj.toString = function() { return JSON.stringify(this); } }"
    End If
    Set GetScriptEngine = soScriptEngine
End Function

Private Function GetJavaScriptLibrary(ByVal sURL As String) As String

    Dim xHTTPRequest As MSXML2.XMLHTTP60
    Set xHTTPRequest = New MSXML2.XMLHTTP60
    xHTTPRequest.Open "GET", sURL, False
    xHTTPRequest.send
    GetJavaScriptLibrary = xHTTPRequest.responseText

End Function

Private Function DecodeJsonString(ByVal JsonString As String) As Object
    Dim oScriptEngine As ScriptControl
    Set oScriptEngine = GetScriptEngine

    Set DecodeJsonString = oScriptEngine.Eval("(" + JsonString + ")")

    Call oScriptEngine.Run("overrideToString", DecodeJsonString) '* this gives JSON rendering instead of "[object Object]"

End Function

Private Function GetJSONObject(ByVal obj As Object, ByVal sKey As String) As Object
    Dim objReturn As Object
    Set objReturn = VBA.CallByName(obj, sKey, VbGet)
    Call GetScriptEngine.Run("overrideToString", objReturn) '* this gives JSON rendering instead of "[object Object]"
    Set GetJSONObject = objReturn
End Function

Private Sub TestJSONParsingWithCallByName2()

    Dim sJsonString As String
    sJsonString = "{'key1': 'value1'  ,'key2': { 'key3': 'value3' } }"


    Dim objJSON As Object
    Set objJSON = DecodeJsonString(sJsonString)

    Stop


    Dim objKey2 As Object
    Set objKey2 = GetJSONObject(objJSON, "key2")
    Debug.Print objKey2
    Stop

End Sub

下面是新代码的屏幕截图,它显示了JScriptTypeInfo变量的字符串化

票数 6
EN

Stack Overflow用户

发布于 2017-10-19 08:35:56

谢谢simple,这就是我想要的,一种将JSON对象转换为string的简单方法。我使用了您的想法并将其与代码合并,但我不喜欢每次创建JSON对象时建立连接和下载脚本的想法。因此,我将JSON2.js代码压缩为一个函数,然后使用它,接下来我将粘贴它,也许有人也会喜欢这个想法。

代码语言:javascript
运行
复制
Private Function JSON2() As String
    'https://stackoverflow.com/questions/37711073/in-excel-vba-on-windows-how-to-get-stringified-json-respresentation-instead-of
    'https://raw.githubusercontent.com/douglascrockford/JSON-js/master/json2.js
    JSON2 = _
        "if(typeof JSON!==""object""){JSON={};}" _
        & "(function(){""use strict"";var rx_one=/^[\],:{}\s]*$/;var rx_two=/\\(?:[""\\\/bfnrt]|u[0-9a-fA-F]{4})/g;var rx_three=/""[^""\\\n\r]*""|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;var rx_four=/(?:^|:|,)(?:\s*\[)+/g;var rx_escapable=/[\\""\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;var rx_dangerous=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;function f(n){return n<10?""0""+n:n;}" _
        & "function this_value(){return this.valueOf();}" _
        & "if(typeof Date.prototype.toJSON!==""function""){Date.prototype.toJSON=function(){return isFinite(this.valueOf())?this.getUTCFullYear()+""-""+" _
        & "f(this.getUTCMonth()+1)+""-""+" _
        & "f(this.getUTCDate())+""T""+" _
        & "f(this.getUTCHours())+"":""+" _
        & "f(this.getUTCMinutes())+"":""+" _
        & "f(this.getUTCSeconds())+""Z"":null;};Boolean.prototype.toJSON=this_value;Number.prototype.toJSON=this_value;String.prototype.toJSON=this_value;}" _
        & "var gap;var indent;var meta;var rep;function quote(string){rx_escapable.lastIndex=0;return rx_escapable.test(string)?""\""""+string.replace(rx_escapable,function(a){var c=meta[a];return typeof c===""string""?c:""\\u""+(""0000""+a.charCodeAt(0).toString(16)).slice(-4);})+""\"""":""\""""+string+""\"""";}" _
        & "function str(key,holder){var i;var k;var v;var length;var mind=gap;var partial;var value=holder[key];if(value&&typeof value===""object""&&typeof value.toJSON===""function""){value=value.toJSON(key);}" _
        & "if(typeof rep===""function""){value=rep.call(holder,key,value);}"
    JSON2 = JSON2 _
        & "switch(typeof value){case""string"":return quote(value);case""number"":return isFinite(value)?String(value):""null"";case""boolean"":case""null"":return String(value);case""object"":if(!value){return""null"";}" _
        & "gap+=indent;partial=[];if(Object.prototype.toString.apply(value)===""[object Array]""){length=value.length;for(i=0;i<length;i+=1){partial[i]=str(i,value)||""null"";}" _
        & "v=partial.length===0?""[]"":gap?""[\n""+gap+partial.join("",\n""+gap)+""\n""+mind+""]"":""[""+partial.join("","")+""]"";gap=mind;return v;}" _
        & "if(rep&&typeof rep===""object""){length=rep.length;for(i=0;i<length;i+=1){if(typeof rep[i]===""string""){k=rep[i];v=str(k,value);if(v){partial.push(quote(k)+(gap?"": "":"":"")+v);}}}}else{for(k in value){if(Object.prototype.hasOwnProperty.call(value,k)){v=str(k,value);if(v){partial.push(quote(k)+(gap?"": "":"":"")+v);}}}}" _
        & "v=partial.length===0?""{}"":gap?""{\n""+gap+partial.join("",\n""+gap)+""\n""+mind+""}"":""{""+partial.join("","")+""}"";gap=mind;return v;}}" _
        & "if(typeof JSON.stringify!==""function""){meta={""\b"":""\\b"",""\t"":""\\t"",""\n"":""\\n"",""\f"":""\\f"",""\r"":""\\r"",""\"""":""\\\"""",""\\"":""\\\\""};JSON.stringify=function(value,replacer,space){var i;gap="""";indent="""";if(typeof space===""number""){for(i=0;i<space;i+=1){indent+="" "";}}else if(typeof space===""string""){indent=space;}" _
        & "rep=replacer;if(replacer&&typeof replacer!==""function""&&(typeof replacer!==""object""||typeof replacer.length!==""number"")){throw new Error(""JSON.stringify"");}" _
        & "return str("""",{"""":value});};}" _
        & "if(typeof JSON.parse!==""function""){JSON.parse=function(text,reviver){var j;function walk(holder,key){var k;var v;var value=holder[key];if(value&&typeof value===""object""){for(k in value){if(Object.prototype.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v;}else{delete value[k];}}}}" _
        & "return reviver.call(holder,key,value);}" _
        & "text=String(text);rx_dangerous.lastIndex=0;if(rx_dangerous.test(text)){text=text.replace(rx_dangerous,function(a){return""\\u""+" _
        & "(""0000""+a.charCodeAt(0).toString(16)).slice(-4);});}" _
        & "if(rx_one.test(text.replace(rx_two,""@"").replace(rx_three,""]"").replace(rx_four,""""))){j=eval(""(""+text+"")"");return(typeof reviver===""function"")?walk({"""":j},""""):j;}" _
        & "throw new SyntaxError(""JSON.parse"");};}}());"
End Function
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37711073

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档