VBA JSON - Разбор нескольких значений - PullRequest
1 голос
/ 03 марта 2020

У меня проблемы с использованием конвертера JSON -VBA с ключом нескольких значений.

У меня есть обычные процедуры рекурсии, написанные для навигации по JSON деревьям, но вот пример простого * 1019 Разбор, который я не могу заставить работать.

См. Это для VBA- JSON программного обеспечения для конвертации , которое является ужасающим c и быстрым.

Окружающая среда: Windows 7 / Доступ 2016 / Частная ЛВС (без Inte rnet)

Вот код:

Option Compare Database
Option Explicit

Sub testparse()
Dim js As String, i As Long, jo As Object, item As Variant
Dim keys(), vals()

' fails on this string
js = "{ !Category!: !Famous Pets!," & _
  "!code!: [!a!,!b!,!c!] }"            ' string with multiple values

' with the following string, this works
js = "{ !Category!: !Famous Pets!," & _
  "    !code!: !singlecodevalue! }"

js = Replace(js, "!", Chr(34)) ' replace ! with quotes

Debug.Print " js = " & js
Set jo = JsonConverter.ParseJson(js) ' returns object with json elements
i = 0
ReDim keys(1 To jo.Count)
ReDim vals(1 To jo.Count)

Debug.Print " Number keys found at top level " & jo.Count
For Each item In jo
    i = i + 1
    keys(i) = item
    vals(i) = jo(item)
    Next item

For i = 1 To jo.Count
    Debug.Print "key " & keys(i) & " = " & vals(i)
    Next i

End Sub


1 Ответ

0 голосов
/ 03 марта 2020

Для каждого элемента, с которым вы сталкиваетесь при прохождении через объект JSON, вы должны определить, с чем имеете дело, особенно если вы заранее не знаете, сколько элементов в массиве! Это становится еще сложнее, если у вас есть составная JSON структура с коллекциями внутри массивов и т. это до доступа к нему. Верхний уровень объекта JSON (при условии использования JsonConverter) всегда будет Dictionary. Таким образом, вы можете рассчитывать на циклическое переключение клавиш словаря верхнего уровня:

Dim json As Dictionary
Set json = JsonConverter.ParseJson(someJsonString)

Dim topLevelKey As String
For Each topLevelKey In json
    Dim item As Variant
    Debug.Print topLevelKey & " = " & item
Next topLevelKey 

Проблема в том, что item не всегда простая строка. Это может быть значение (String), массив (Collection) или группа (Dictionary). См. этот ответ в качестве хорошего справочника.

По сути, это означает, что вы должны проверить каждый item, прежде чем использовать его. Таким образом, вы можете проверить это следующим образом:

Select Case TypeName(item)
    Case "Collection"
        '--- loop through the item as a Collection
    Case "Dictionary"
        '--- loop through the item as a Dictionary
    Case Else
        '--- the item is a value of some type (String, Boolean, etc)
End Select

В моем примере здесь я создал подпрограмму с именем ParseItem, которая проверяет каждый из элементов таким образом. Переработка вашего исходного кода в приведенный ниже пример:

Option Explicit

Sub testparse()
    Dim js As String, i As Long, jo As Object, item As Variant
    Dim keys(), vals()

    ' fails on this string
    js = "{ !Category!: !Famous Pets!," & _
         "!code!: [!a!,!b!,!c!] }"               ' string with multiple values

    ' with the following string, this works
    '    js = "{ !Category!: !Famous Pets!," & _
    '         "    !code!: !singlecodevalue! }"

    '--- compound example
    '    js = "{ !Category!: !Famous Pets!,!code!: [!a!,!b!,{!c! : { !c1! : !1!, !c2!:!2!}}] }"

    js = Replace(js, "!", Chr(34))               ' replace ! with quotes

    Debug.Print "----------------------"
    Debug.Print "js = " & js
    Set jo = JsonConverter.ParseJson(js)         ' returns object with json elements
    ParseDictionary 1, "root", jo
End Sub

Private Sub ParseCollection(ByVal level As Long, _
                            ByVal key As String, _
                            ByRef jsonCollection As Variant)
    Dim item As Variant
    For Each item In jsonCollection
        ParseItem level, key, item
    Next item
End Sub

Private Sub ParseDictionary(ByVal level As Long, _
                            ByVal key As String, _
                            ByRef jsonDictionary As Variant)
    Dim dictKey As Variant
    For Each dictKey In jsonDictionary
        ParseItem level, dictKey, jsonDictionary(dictKey)
    Next dictKey
End Sub

Private Sub ParseItem(ByVal level As Long, _
                      ByVal key As String, _
                      ByRef item As Variant)
    Select Case TypeName(item)
    Case "Collection"
        Debug.Print Format(level + 1, "00 ") & key & " (collection)"
        ParseCollection (level + 1), key, item
    Case "Dictionary"
        Debug.Print Format(level + 1, "00 ") & key & " (dictionary)"
        ParseDictionary (level + 1), key, item
    Case Else
        Debug.Print Format(level, "00 ") & key & " = " & item
    End Select
End Sub
...