从 JSCRIPT/VBA 中的重度嵌套 JSON 中删除层(键)
Remove layers (keys) from heavily nested JSON in JSCRIPT/VBA
我正在使用 scriptcontrol/jscript 解析 VBA 中的重度嵌套 JSON。
生成的 JSON 对象是超级嵌套的,并且具有重复出现的 'useless' 级别/层,称为 'buckets'。
有没有办法可以从我的 json 字符串或解析的 json 对象中一起删除这些?
想象一下:
回应。0.buckets.0.aggregations.0.10.buckets.0.5.buckets.0.9.buckets.0.20.buckets.0 .8.buckets.0.13.buckets.0.14.buckets.0.15.buckets.0.16.buckets.0.19.buckets.0.18.buckets.0.21.doc_count_error_upper_bound
我只需要 'doc_count_error_upper_bound' 值,并且基本上可以不使用所有 0 和所有存储桶,从而减少嵌套到:
responses.aggregations.10.5.9.20.8.13.14.15.16.19.18.21.doc_count_error_upper_bound
这仍然是非常嵌套的,但已经让我省去了很多麻烦。
我只是不知道如何使用 VBA (es3) 中的 jscript/scriptcontrol 来做到这一点。
源数据来自 Kibana 仪表板(http://demo.elastic.co/ 上的示例)
感谢您的帮助!
贾斯珀
更新:
关于 VBA 代码的问题 - 我拥有的 VBA 代码是无关紧要的,因为它是通过 scriptcontrol 将 json 字符串加载到对象中的标准方法。
我不使用 EVAL,但出于示例目的,它类似于以下内容:
Dim Scr as Object, Json as Object
Set Scr = CreateObject("Scriptcontrol")
Scr.Language = "Jscript"
Set Json = Scr.Eval("(" & WinHTTP.ResponseText & ")")
我无法分享 JSON 字符串的示例,因为它包含敏感数据。
但最终,这不是问题。
考虑示例 https://adobe.github.io/Spry/data/json/donuts.js
在顶部,"batter" 作为 "batters" 和不同 ID 之间的键。如果我想删除该密钥,但保留基础 ID 数据 - 我将如何通过在 VBA 的 scriptcontrol 中工作的 js 脚本来做到这一点?
更新:
omegastripes 的答案非常有效,但是,我没有意识到我想删除的一些键('buckets' 和“0”等)在它们下面有键和值。
让我们以甜甜圈为例,只是稍作改动 - 参见此处:
https://pastebin.com/WxYir7vK
现在我想删除“0”、“1”、“2”等键而不丢失底层子键。
但是,要使 omegastripes 代码起作用,我必须从所有层/整个 json 中删除键 'sequence'、'variant'、'name' 和 'ppu' .
我可以为其中之一做这个,对于具有以下功能的一层:
function unseat(obj, prop) { for(var k in obj[prop]) obj[k] = obj[prop][k]; delete obj[prop]; return obj; }
然后调用函数 'unseat (JSONObj, "variant")' - 这有效,但一次仅适用于四个变量之一且仅适用于一层。
我怎样才能改变它,以便我可以将它从整个对象中删除,同时删除所有四个对象,以便之后我可以使用 omegastripes 代码来解包。
总结
1) 我取这个 json 字符串:https://pastebin.com/WxYir7vK
2) 将其解析成脚本控制成VBA
3) 遍历它并删除所有 'sequence'、'variant'、'name' 和 'ppu' key/value 对
4) 通过 omegastripes 代码解包。
第 1 / 2 步和第 4 步已完成 - 但如何做第 3 步?
谢谢!
使用ScriptControl解析JSON有以下缺点(详见this answer):
- 系统环境暴露于响应中收到的恶意代码注入。
- ScriptControl 在 64 位 MS Office 上不可用。
无论如何,如果您确信在 JScript 环境中操作是唯一的方法,您可以使用以下函数解开过多的对象嵌套和数组结构:
function gParse(sample) {
return eval('(' + sample + ')');
};
function gUnwrap(sample) {
for (var key in sample) {
sample[key] = gUnwrap(sample[key]);
};
var count = 0;
for (var key in sample) {
count++;
if (count == 2) break;
};
if (count == 1) {
var type = gGetType(sample);
if (type == 'Array' || type == 'Object') {
var type = gGetType(sample[key]);
if (type == 'Array' || type == 'Object') {
return sample[key];
}
}
};
return sample;
};
function gGetType(sample) {
return {}.toString.call(sample).slice(8, -1);
};
这可以在 VBA 中完成,如下所示:
Option Explicit
Sub Test()
Dim sJSON As String
Dim ParseJSON As Object
Dim UnwrapJSON As Object
Dim oJSON As Object
With CreateObject("MSXML2.XMLHTTP")
.Open "GET", "https://adobe.github.io/Spry/data/json/donuts.js", False
.send
sJSON = .responseText
End With
With CreateObject("htmlfile")
With .parentWindow
.execScript "function gParse(sample) {return eval('(' + sample + ')')};"
.execScript "function gUnwrap(sample) {for (var key in sample) {sample[key] = gUnwrap(sample[key]);}; var count = 0; for (var key in sample) {count++; if (count == 2) break;}; if (count == 1) {var type = gGetType(sample); if (type == 'Array' || type == 'Object') {var type = gGetType(sample[key]); if (type == 'Array' || type == 'Object') {return sample[key];}}}; return sample;};"
.execScript "function gGetType(sample) {return {}.toString.call(sample).slice(8, -1)};"
Set ParseJSON = .gParse
Set UnwrapJSON = .gUnwrap
End With
End With
Set oJSON = UnwrapJSON(ParseJSON(sJSON))
End Sub
当地人 window 显示 the sample you provided 的 JSON 对象如下:
并展开 JSON 对象:
我正在使用 scriptcontrol/jscript 解析 VBA 中的重度嵌套 JSON。 生成的 JSON 对象是超级嵌套的,并且具有重复出现的 'useless' 级别/层,称为 'buckets'。
有没有办法可以从我的 json 字符串或解析的 json 对象中一起删除这些?
想象一下:
回应。0.buckets.0.aggregations.0.10.buckets.0.5.buckets.0.9.buckets.0.20.buckets.0 .8.buckets.0.13.buckets.0.14.buckets.0.15.buckets.0.16.buckets.0.19.buckets.0.18.buckets.0.21.doc_count_error_upper_bound
我只需要 'doc_count_error_upper_bound' 值,并且基本上可以不使用所有 0 和所有存储桶,从而减少嵌套到:
responses.aggregations.10.5.9.20.8.13.14.15.16.19.18.21.doc_count_error_upper_bound
这仍然是非常嵌套的,但已经让我省去了很多麻烦。 我只是不知道如何使用 VBA (es3) 中的 jscript/scriptcontrol 来做到这一点。
源数据来自 Kibana 仪表板(http://demo.elastic.co/ 上的示例)
感谢您的帮助!
贾斯珀
更新: 关于 VBA 代码的问题 - 我拥有的 VBA 代码是无关紧要的,因为它是通过 scriptcontrol 将 json 字符串加载到对象中的标准方法。
我不使用 EVAL,但出于示例目的,它类似于以下内容:
Dim Scr as Object, Json as Object
Set Scr = CreateObject("Scriptcontrol")
Scr.Language = "Jscript"
Set Json = Scr.Eval("(" & WinHTTP.ResponseText & ")")
我无法分享 JSON 字符串的示例,因为它包含敏感数据。 但最终,这不是问题。 考虑示例 https://adobe.github.io/Spry/data/json/donuts.js
在顶部,"batter" 作为 "batters" 和不同 ID 之间的键。如果我想删除该密钥,但保留基础 ID 数据 - 我将如何通过在 VBA 的 scriptcontrol 中工作的 js 脚本来做到这一点?
更新:
omegastripes 的答案非常有效,但是,我没有意识到我想删除的一些键('buckets' 和“0”等)在它们下面有键和值。
让我们以甜甜圈为例,只是稍作改动 - 参见此处: https://pastebin.com/WxYir7vK
现在我想删除“0”、“1”、“2”等键而不丢失底层子键。 但是,要使 omegastripes 代码起作用,我必须从所有层/整个 json 中删除键 'sequence'、'variant'、'name' 和 'ppu' .
我可以为其中之一做这个,对于具有以下功能的一层:
function unseat(obj, prop) { for(var k in obj[prop]) obj[k] = obj[prop][k]; delete obj[prop]; return obj; }
然后调用函数 'unseat (JSONObj, "variant")' - 这有效,但一次仅适用于四个变量之一且仅适用于一层。 我怎样才能改变它,以便我可以将它从整个对象中删除,同时删除所有四个对象,以便之后我可以使用 omegastripes 代码来解包。
总结
1) 我取这个 json 字符串:https://pastebin.com/WxYir7vK
2) 将其解析成脚本控制成VBA
3) 遍历它并删除所有 'sequence'、'variant'、'name' 和 'ppu' key/value 对
4) 通过 omegastripes 代码解包。
第 1 / 2 步和第 4 步已完成 - 但如何做第 3 步?
谢谢!
使用ScriptControl解析JSON有以下缺点(详见this answer):
- 系统环境暴露于响应中收到的恶意代码注入。
- ScriptControl 在 64 位 MS Office 上不可用。
无论如何,如果您确信在 JScript 环境中操作是唯一的方法,您可以使用以下函数解开过多的对象嵌套和数组结构:
function gParse(sample) {
return eval('(' + sample + ')');
};
function gUnwrap(sample) {
for (var key in sample) {
sample[key] = gUnwrap(sample[key]);
};
var count = 0;
for (var key in sample) {
count++;
if (count == 2) break;
};
if (count == 1) {
var type = gGetType(sample);
if (type == 'Array' || type == 'Object') {
var type = gGetType(sample[key]);
if (type == 'Array' || type == 'Object') {
return sample[key];
}
}
};
return sample;
};
function gGetType(sample) {
return {}.toString.call(sample).slice(8, -1);
};
这可以在 VBA 中完成,如下所示:
Option Explicit
Sub Test()
Dim sJSON As String
Dim ParseJSON As Object
Dim UnwrapJSON As Object
Dim oJSON As Object
With CreateObject("MSXML2.XMLHTTP")
.Open "GET", "https://adobe.github.io/Spry/data/json/donuts.js", False
.send
sJSON = .responseText
End With
With CreateObject("htmlfile")
With .parentWindow
.execScript "function gParse(sample) {return eval('(' + sample + ')')};"
.execScript "function gUnwrap(sample) {for (var key in sample) {sample[key] = gUnwrap(sample[key]);}; var count = 0; for (var key in sample) {count++; if (count == 2) break;}; if (count == 1) {var type = gGetType(sample); if (type == 'Array' || type == 'Object') {var type = gGetType(sample[key]); if (type == 'Array' || type == 'Object') {return sample[key];}}}; return sample;};"
.execScript "function gGetType(sample) {return {}.toString.call(sample).slice(8, -1)};"
Set ParseJSON = .gParse
Set UnwrapJSON = .gUnwrap
End With
End With
Set oJSON = UnwrapJSON(ParseJSON(sJSON))
End Sub
当地人 window 显示 the sample you provided 的 JSON 对象如下:
并展开 JSON 对象: