Использование VBA-JSON для извлечения из API «ошибка: объект не поддерживает это свойство или метод здесь»? - PullRequest
0 голосов
/ 19 февраля 2019

Попытка получить определенные данные из API с помощью VBA-JSON.Получите ошибку: объект не поддерживает это свойство или метод здесь |Для каждого ключа в json.Keys.Пытаясь выяснить, почему.

Когда я пытаюсь "Для каждого ключа в json.Key", я получаю код ошибки в заголовке.Я знаю, что это потому, что defender_list является массивом, поэтому мне нужно определить объект, но я изо всех сил пытаюсь создать оператор For для объекта (если это то, что мне нужно сделать).Я взял часть «За каждый ключ», потому что знаю, что это неправильно.

Option Explicit

Public Sub WriteOutBattleInfo()
    Dim headers(), r As Long, i As Long, json As Object, key As Variant, ws As Worksheet, defenderList As Object, monsterInfo As Object
    Set ws = ThisWorkbook.Worksheets("Sheet3")
    headers = Array("Username", "Avg BP", "Avg Level", "Opp. Address", "Player ID", "Catch Number", "Monster ID", "Type 1", "Type 2", "Gason Y/N", "Ancestor 1", "Ancestor 2", "Ancestor 3", "Class ID", "Total Level", "Exp", "HP", "PA", "PD", "SA", "SD", "SPD", "Total BP")

    With CreateObject("MSXML2.XMLHTTP")
        .Open "GET", "https://www.etheremon.com/api/ema_battle/get_rank_castles?v=8588587&trainer_address=0x2fef65e4d69a38bf0dd074079f367cdf176ec0de", False
        .Send
        Set json = JsonConverter.ParseJson(.ResponseText)("data")("defender_list") 'dictionary of dictionaries
    End With
    r = 2
    ws.Cells(1, 1).Resize(1, UBound(headers) + 1) = headers

Редактировать: пробовал это

Dim obj As Variant
Dim monsterInfo, obj2
Dim types, obj3
Dim ancestors, obj4
Dim totalBattleStats, obj5

For Each obj In json
    Debug.Print obj("username")
    Debug.Print obj("avg_bp")
    Debug.Print obj("avg_level")
    Debug.Print obj("player_id")

    Set monsterInfo = obj("monster_info")
    For Each obj2 In monsterInfo
        Debug.Print obj2("create_index")
        Debug.Print obj2("monster_id")

        Set types = obj("types")
        Debug.Print obj3("types")

        Debug.Print obj2("is_gason")

        Set ancestors = obj("ancestors")
        Debug.Print obj4("ancestors")

        Debug.Print obj2("class_ID")
        Debug.Print obj2("total_level")
        Debug.Print obj2("exp")

        Set totalBattleStats = obj("total_battle_stats")
        Debug.Print obj5("total_battle_stats")

        Debug.Print obj2("total_bp")

Next obj

      Cells.Select
      Selection.Columns.AutoFit



  End Sub

Я хочу получить специально из "defender_list".Каждое «имя пользователя» имеет 6 месяцев, связанных с ним.Самое главное, я хочу получить статистику от каждого из этих монов, но я перечислил все, что мне нужно, в заголовках =.Имена переменных для кода: «username», «avg_bp», «avg_level», «player_id», а затем в «monster_info» находятся «create_index», «monster» id »« types »(массив type1, type2),« is_gason"," ancestors "(предок массива 1,2,3)," class_id "," total_level "," exp ", total_battle_stats (массив hp, pa, pd, sa, sd, spd)," total_bp ".

json sample

Ожидаемый результат:

output

Где:
Имя пользователя- "username"
Avg BP - "avg_bp"
Avg Level - "avg_level"
Идентификатор игрока - "player_id"
Номер улова - "create_index"
Идентификатор монстра - идентификатор "monster""
Тип 1, Тип 2 -" типы "(массив тип1, тип2)
Гасон -" is_gason "
Предок 1, Предок 2, Предок 3 -" предки "(предок массива 1,2,3)
Идентификатор класса - "class_id"
Общий уровень - "total_level"
Exp - "exp"
HP, PA, PD, SA, SD, SPD - "total_battle_stats" (массив hp, pa, pd, sa, sd, spd)
Total BP - "total_bp"

Все после мнayer_ID в этом списке специфичен для mon.Каждое имя пользователя имеет 6 месяцев, что означает 6 строк на имя пользователя.То, что перед player_ID, можно просто повторить для строк 1-6, это не имеет значения.

Ответы [ 2 ]

0 голосов
/ 19 февраля 2019

У вас есть несколько смущающих факторов.

1) У вас есть вложенные монстры в каждом игроке.Вам необходимо учесть это и продублировать начальную информацию о строках для этих строк.

2) Из-за ваших заголовков вы предположили, что структура json является и регулярной, и содержит одинаковое количество элементов / ключей в каждом объекте в пределахJSON.Это не тот случай, например, MonsterId 47023 имеет только одно значение Type и не ancestors.Я использую некоторые жестко закодированные значения, чтобы установить цикл на основе ваших заголовков, то есть, что должно быть 2 значения типа и 3 значения предка.Я обертываю это в On Error Resume Next On Error GoTo O, чтобы подавить возникающую ошибку при попытке доступа к несуществующему элементу.Таким образом вводится пробел.

Пример выброса:

image


VBA:

Option Explicit   
Public Sub WriteOutBattleInfo()
    Dim headers(), json As Object, key As Variant, ws As Worksheet
    Set ws = ThisWorkbook.Worksheets("Sheet3")
    headers = Array("Username", "Avg BP", "Avg Level", "Opp. Address", "Player ID", "Catch Number", "Monster ID", "Type 1", "Type 2", "Gason Y/N", "Ancestor 1", "Ancestor 2", "Ancestor 3", "Class ID", "Total Level", "Exp", "HP", "PA", "PD", "SA", "SD", "SPD", "Total BP")

    With CreateObject("MSXML2.XMLHTTP")
        .Open "GET", "https://www.etheremon.com/api/ema_battle/get_rank_castles?v=8588587&trainer_address=0x2fef65e4d69a38bf0dd074079f367cdf176ec0de", False
        .send
        Set json = JsonConverter.ParseJson(.responseText)("data")("defender_list") 'Collection of dictionaries
    End With
    Dim dict As Object, c As Long, r As Long, item As Object, key2 As Variant, results(), item2 As Long
    ReDim results(1 To json.Count * json(1)("monster_info").Count, 1 To UBound(headers) + 1) '<== +1 here if can establish what catch number is

    Dim j As Long
    For Each dict In json
        r = r + 1: c = 1
        For Each key In dict.keys
            Select Case key
            Case "username", "avg_bp", "avg_level", "address", "player_id"
                results(r, c) = dict(key)
                c = c + 1
            Case "monster_info"
                Dim monsterNumber As Long, temp(1 To 5)
                monsterNumber = 1
                For Each item In dict(key)       'collection of dictionaries               
                    If monsterNumber = 1 Then
                        For j = 1 To 5
                            temp(j) = results(r, j)
                        Next
                    Else
                        r = r + 1
                        For j = 1 To 5
                            results(r, j) = temp(j)
                        Next
                    End If
                    For Each key2 In item.keys
                        Select Case key2
                        Case "create_index", "monster_id", "is_gason", "class_id", "total_level", "exp", "total_bp"
                            results(r, c) = item(key2)
                            c = c + 1
                            Case "types" '<==expecting 2. Can get 1. Maybe different count?
                            For item2 = 1 To 2
                                On Error Resume Next
                                results(r, c) = item(key2).item(item2)
                                c = c + 1
                                On Error GoTo 0
                            Next
                            Case "ancestors" '<== expecting 3. Can get 0. Maybe different number
                            For item2 = 1 To 3
                                On Error Resume Next
                                results(r, c) = item(key2).item(item2)
                                c = c + 1
                                On Error GoTo 0
                            Next
                            Case "battle_stats"
                            For item2 = 1 To item(key2).Count
                                results(r, c) = item(key2).item(item2)
                                c = c + 1
                            Next
                        End Select
                    Next
                    c = 6: monsterNumber = monsterNumber + 1
                Next item
            End Select
        Next
    Next
    ws.Cells(1, 1).Resize(1, UBound(headers) + 1) = headers
    ws.Cells(2, 1).Resize(UBound(results, 1), UBound(results, 2)) = results
End Sub

Пример вывода:

enter image description here

0 голосов
/ 19 февраля 2019

Это должно работать (например):

Dim obj 'as variant
Dim mInfo, obj2
For Each obj in json
    Debug.Print obj("username")
    Set mInfo = obj("monster_info")
    For Each obj2 in mInfo
        Debug.Print obj2("trainer")
        Debug.Print obj2("monster_id")
    Next obj2
Next obj
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...