json - 使用 VBA 和 VBA-JSON 从 Wordpress API 访问 JSON 数据
问题描述
我正在构建一个 VBA 应用程序,该应用程序使用从网络上抓取的资源创建和修改 Wordpress 网站页面。Wordpress API 返回一个 JSON 文件,但不支持在 VBA 中解析 JSON,因此我从 GitHub 导入了 VBA-JSON。这是子程序:
Sub Wordpress()
'
' Wordpress API Test
'
Dim wpResp As Variant
Dim sourceSheet As String
Dim resourceURL As String
sourceSheet = "Resources"
resourceURL = Sheets(sourceSheet).Cells(6, 1)
wpResp = getJSON(resourceURL + "/wp-json/wp/v2/posts")
End Sub
以及它调用的函数。
Function getJSON(link) As Object
Dim response As String
Dim json As Object
On Error GoTo recovery
Dim retryCount As Integer
retryCount = 0
Dim web As MSXML2.XMLHTTP60
Set web = New MSXML2.XMLHTTP60
the_start:
web.Open "GET", link, False, UserName, pw
web.setRequestHeader "Content-type", "application/json"
web.send
response = web.responseText
While web.readyState <> 4
DoEvents
Wend
On Error GoTo 0
Debug.Print link
Debug.Print web.Status; "XMLHTTP status "; web.statusText; " at "; Time
Set json = JsonConverter.ParseJson(response)
'getJSON = json ' this line produces Object variable or With block variable not set error but I can deal with it later
Exit Function
recovery:
retryCount = retryCount + 1
Debug.Print "Error number: " & Err.Number & " " & Err.Description & " Retry " & retryCount
Application.StatusBar = "Error number: " & Err.Number & " " & Err.Description & " Retry " & retryCount
If retryCount < 4 Then GoTo the_start Else Exit Function
End Function
此代码返回一个包含 1 个项目的对象/集合,其中包含一个包含 24 个项目的变体/对象/字典,但我不知道如何访问这些项目。这是一个屏幕截图:
如果我使用即时窗口查询 ?json.count 我得到正确的结果“1”,但在网上研究了大约六个小时并尝试了尽可能多的变体后,我仍然坚持如何访问其他 24.
这是JSON:
[{"id":1,"date":"2018-06-22T18:13:00","date_gmt":"2018-06-22T22:13:00","guid":{"rendered":"http:\/\/mytestsite.org\/?p=1"},"modified":"2018-06-22T18:13:00","modified_gmt":"2018-06-22T22:13:00","slug":"hello-world","status":"publish","type":"post","link":"http:\/\/mytestsite.org\/hello-world\/","title":{"rendered":"Blog Post Title"},"content":{"rendered":"<p>What goes into a blog post? Helpful, industry-specific content that: 1) gives readers a useful takeaway, and 2) shows you’re an industry expert. <\/p>\n<p>Use your company’s blog posts to opine on current industry topics, humanize your company, and show how your products and services can help people.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>What goes into a blog post? Helpful, industry-specific content that: 1) gives readers a useful takeaway, and 2) shows you’re…<\/p>\n","protected":false},"author":1,"featured_media":212,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[],"_links":{"self":[{"href":"http:\/\/mytestsite.org\/wp-json\/wp\/v2\/posts\/1"}],"collection":[{"href":"http:\/\/mytestsite.org\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/mytestsite.org\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/mytestsite.org\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/mytestsite.org\/wp-json\/wp\/v2\/comments?post=1"}],"version-history":[{"href":"http:\/\/mytestsite.org\/wp-json\/wp\/v2\/posts\/1\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/mytestsite.org\/wp-json\/wp\/v2\/media\/212"}],"wp:attachment":[{"href":"http:\/\/mytestsite.org\/wp-json\/wp\/v2\/media?parent=1"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/mytestsite.org\/wp-json\/wp\/v2\/categories?post=1"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/mytestsite.org\/wp-json\/wp\/v2\/tags?post=1"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}]
归根结底,我希望能够从几个互联网资源中提取和整理几百页的 WP 内容,并使用这个应用程序让它们保持最新。只要我们不脱离 VBA,这里的问题之外的进一步建议也会很有用。
解决方案
JsonConverter返回VBA.Collections Scripting.Dictionaries 和 Values 的集合。为了理解输出,您必须测试TypeName
所有返回值。
真正的问题是“如何浏览json
对象(或任何未知对象)并访问其中的值。
即时窗口
使用 OP 帖子中的Immediate Window
和json
对象,我将尝试描述思维过程(以必读书籍的风格:The Little Schemer)
' What is json?
?TypeName(JSON)
Collection
'json is a collection
'How big is JSON
?JSON.Count
1
'JSON is a collection of 1 Item
'What is Type that Item?
?TypeName(JSON(1))
Dictionary
'JSON(1) is a Dictionary
'What is the first key in the JSON(1) Dictionary?
?JSON(1).Keys()(0)
id
'The first key in the JSON(1) Dictionary is "id"
'What is the Type of the value of "id"?
?TypeName(JSON(1)("id"))
Double
'JSON(1)("id") is a number
'What is its value
?JSON(1)("id")
1
当然,考虑到这个 JSON 对象中的嵌套量,这个过程可能会变得乏味。
JSON(1)("_links")("居里")(1)("模板化")
集合|字典|字典|集合|布尔值
所以我想最好的办法是编写一个函数,将所有访问器打印到Immediate Window
并从那里开始。
PrintJSONAccessors:Sub
Sub PrintJSONAccessors(JSON As Variant, Optional Prefix As String)
Dim data As Variant, Key As Variant, Value As Variant
Dim Accessor As String, ArrayAccessor As String
Dim n As Long
If TypeName(JSON) = "Collection" Then
For n = 1 To JSON.Count
Accessor = Prefix & "(" & n & ")"
If TypeName(JSON(n)) = "Dictionary" Or TypeName(JSON(n)) = "Collection" Then
PrintJSONAccessors JSON(n), Accessor
Else
Debug.Print Accessor
End If
Next
Else
For Each Key In JSON
If TypeName(Key) = "Dictionary" Or TypeName(Key) = "Collection" Then
PrintJSONAccessors Key, Prefix
ElseIf TypeName(JSON(Key)) = "Dictionary" Or TypeName(JSON(Key)) = "Collection" Then
Accessor = Prefix & "(" & Chr(34) & Key & Chr(34) & ")"
PrintJSONAccessors JSON(Key), Accessor
ElseIf TypeName(JSON(Key)) = "Dictionary" Then
Accessor = Prefix & "(" & Chr(34) & Key & Chr(34) & ")"
PrintJSONAccessors JSON(Key), Accessor
ElseIf TypeName(JSON(Key)) = "Variant()" Then
data = JSON(Key)
For n = LBound(data) To UBound(data)
Accessor = Prefix & "(" & Chr(34) & Key & Chr(34) & ")"
ArrayAccessor = Prefix & "(" & Chr(34) & Key & Chr(34) & ")" & "(" & n & ")"
If TypeName(data(n)) = "Dictionary" Then
PrintJSONAccessors data(n), ArrayAccessor
Else
Debug.Print ArrayAccessor
End If
Next
Else
Accessor = Prefix & "(" & Chr(34) & Key & Chr(34) & ")"
Debug.Print Accessor
End If
Next
End If
End Sub
用法:
PrintJSONAccessors JSON, "?JSON"
似乎MSScriptControl.ScriptControl
只有在 32 位系统上有效。我想这就是 SIM 在他的评论中所暗示的。虽然,我的回答是 IMO 正确的,但您应该忽略下一部分的评论。
仅供参考:我在Code Review上发布了一个函数,该函数将 JSON 解析为数组和字典函数,以使用 VBA 集合和数组返回类似 JSON 的对象。它不是JsonConverter或 omegastripes 的JSON.Bas的替代品。它演示了您可以添加JScript代码并使用它来处理 JSON。
CreateObject("MSScriptControl.ScriptControl")
推荐阅读
- logging - 任意点监控:如何按错误类型过滤
- node.js - React Native env-cmd 不会拉入变量,但如果 .env-cmdrc JSON 格式错误,则会失败,因此它正在加载它
- javascript - 使用 nodemailer 发送邮件到 office@company.ro 地址
- java - FFmpeg 裁剪过大无效
- microsoft-graph-api - Graph API OneNote:使用页面内容创建部分
- python - 显示存在于子列表中但不存在于另一个子列表的列表中的值
- bash - 未找到 Aws CloudFormation 命令
- debugging - GCC:发送部分调试信息,同时在内部保留完整的调试信息
- ocaml - 在 OCaml 中使用 Formatter 理解漂亮的打印
- python - Websocket 不使用 Python 接收消息