Dans Excel VBA sous Windows, Comment obtenir une représentation JSON stringifiée au lieu de" [object Object] " pour les variables JSON parsées?
répondant à ma propre question ici.
J'ai fait quelques travaux avec JSON dans Excel VBA et beaucoup de conclusions à poster que je vais le faire dans le format Q & A
https://stackoverflow.com/help/self-answer http://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-own-questions /
donc ailleurs sur stackoverflow on peut voir des questions sur l'analyse de JSON dans VBA mais ils semblent manquer une astuce ou de deux.
pour commencer, je n'utilise pas les bibliothèques d'analyse JSON personnalisées et j'utilise plutôt la méthode Eval de ScriptControl comme base de tout mon code JSON. Et nous exprimons également une préférence de Microsoft solutions natives.
Voici une question préalable dans Excel VBA sur Windows, comment atténuer la question de la syntaxe de point traversée de JSON parsemé brisée par le comportement de capitalisation D'IDE? sur laquelle cette question s'appuie. Il montre comment utiliser VBA.CallByName est plus robuste que d'utiliser la syntaxe de point pour traverser un objet JSON analysé. Aussi une autre question préalable dans Excel VBA sur Windows, comment boucler à travers un tableau JSON analysé? montre comment il peut également être utilisé pour accéder aux éléments du tableau. Mais CallByName renvoie un type de variable curieux qui apparaît dans la fenêtre Watch comme Object/JScriptTypeInfo et si un type de Débogage.D'impression dans la fenêtre (ou de la pointe sur la variable), on obtient l'imprécis "[object Objet."]
Comment Pouvons-nous améliorer cela et obtenir un JSON stringified represenation?
Voici une capture d'écran de ce que vous voyez dans les fenêtres immédiates après un débogage.D'impression (? et si vous passez la souris sur une variable.
C'est la Question 3 de la série de 5. Voici la série complète
Q2 en Excel VBA sur Windows, Comment faire une boucle à travers un tableau JSON parsed?
2 réponses
les réponses à d'autres questions sur le débordement de la pile qui se rapportent au travail avec des objets JSON analysés utilisent une approche de mini-script et nous pouvons utiliser cette approche ici.
tout d'Abord, nous reconnaissons que Douglas Crockford est l'auteur de 'Javascript: Les Bonnes Pièces" ( http://shop.oreilly.com/product/9780596517748.do ) et est expert en javascript. Nous sommes donc heureux d'adopter son code en ce qui concerne la stringification. Nous pouvons obtenir son code avec un HTTP Xml simple Demande (généralement raccourci à XHR) et passer le résultat de retour à la méthode Addcode de ScriptControl. Puis ajouter du code qui nous permet de modifier la représentation par défaut De" [objet objet] " en appelant à la bibliothèque de Douglas. Et ensuite, assurez-vous que nous ajoutons dynamiquement ce contrôleur à toutes nos variables JScriptTypeInfo., à la fois ce qui sort de la méthode Eval de ScriptControl que nous enveloppons de décodage() et aussi ce qui sort de VBA.CallByName que nous enveloppons avec GetJSONObject().
ainsi,
'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
voici une capture d'écran avec le nouveau code qui montre une stringification des variables JScriptTypeInfo
Merci Meaden, c'est ce que je cherchais, une façon simple de convertir un objet JSON en chaîne. J'ai utilisé vos idées et je les ai fusionnées avec mon code, mais je n'ai pas aimé l'idée de faire une connexion et de télécharger le script chaque fois que j'avais besoin de créer un objet JSON. donc, j'ai compressé le JSON2.JS code dans une fonction et l'a utilisé à la place que je vais coller la prochaine peut-être que quelqu'un aimera l'idée aussi.
Private Function JSON2() As String
'/q/in-excel-vba-on-windows-how-to-get-stringified-json-respresentation-instead-of-object-object-for-parsed-json-variables-59998/"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