Я пытаюсь разобрать следующий сложный JSON из API Zoho CRM в VB

У меня та же проблема, что и в этом вопросе

Мне удалось заставить код работать на C#, однако я пишу свою программу на Visual Basic. Я прогнал код через конвертер и получил вот это:

Public Class Form1

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Dim html As String = String.Empty
    Dim url As String = "https://crm.zoho.com/crm/private/json/Contacts/searchRecords?authtoken=0e0dd5f8153bc0a1299766b32d09e4f7&&scope=crmapi&fromIndex=1&toIndex=200&criteria=(Store:3110)"

    Dim request As HttpWebRequest = DirectCast(WebRequest.Create(url), HttpWebRequest)
    request.AutomaticDecompression = DecompressionMethods.GZip

    Using response As HttpWebResponse = DirectCast(request.GetResponse(), HttpWebResponse)
        Using stream As Stream = response.GetResponseStream()
            Using reader As New StreamReader(stream)
                html = reader.ReadToEnd()
            End Using
        End Using
    End Using


    Dim loContactList As New List(Of Contact)()
    Dim loContact As Contact = Nothing

    Dim respone As ResponseActual = JsonConvert.DeserializeObject(Of ResponseActual)(html)

    For Each row var In respone.Response.Result.Contacts.Row
        loContact = New Contact()

        Dim rowItem = row.FL.ToList()

        Try
            loContact.ContactID = rowItem.Where(Of FL)(Function(s, t) s.Val = "CONTACTID").[Select](Function(x) x.Content).[Single]()
        Catch
        End Try
        Try
            loContact.OwnerID = rowItem.Where(Of FL)(Function(s, t) s.Val = "SMOWNERID").[Select](Function(x) x.Content).[Single]()
        Catch
        End Try
        Try
            loContact.ContactOwner = rowItem.Where(Of FL)(Function(s, t) s.Val = "Contact Owner").[Select](Function(x) x.Content).[Single]()
        Catch
        End Try
        Try
            loContact.FirstName = rowItem.Where(Of FL)(Function(s, t) s.Val = "First Name").[Select](Function(x) x.Content).[Single]()
        Catch
        End Try
        Try
            loContact.LastName = rowItem.Where(Of FL)(Function(s, t) s.Val = "Last Name").[Select](Function(x) x.Content).[Single]()
        Catch
        End Try
        Try
            loContact.Email = rowItem.Where(Of FL)(Function(s, t) s.Val = "Email").[Select](Function(x) x.Content).[Single]()
        Catch
        End Try
        Try
            loContact.CreatorID = rowItem.Where(Of FL)(Function(s, t) s.Val = "SMCREATORID").[Select](Function(x) x.Content).[Single]()
        Catch
        End Try
        Try
            loContact.CreatedBy = rowItem.Where(Of FL)(Function(s, t) s.Val = "Created By").[Select](Function(x) x.Content).[Single]()
        Catch
        End Try
        Try
            loContact.ModifiedByID = rowItem.Where(Of FL)(Function(s, t) s.Val = "MODIFIEDBY").[Select](Function(x) x.Content).[Single]()
        Catch
        End Try
        Try
            loContact.ModifiedBy = rowItem.Where(Of FL)(Function(s, t) s.Val = "Modified By").[Select](Function(x) x.Content).[Single]()
        Catch
        End Try
        Try
            loContact.CreatedTime = Convert.ToDateTime(rowItem.Where(Of FL)(Function(s, t) s.Val = "Created Time").[Select](Function(x) x.Content).[Single]())
        Catch
        End Try
        Try
            loContact.ModifiedTime = Convert.ToDateTime(rowItem.Where(Of FL)(Function(s, t) s.Val = "Modified Time").[Select](Function(x) x.Content).[Single]())
        Catch
        End Try
        Try
            loContact.LastActivityTime = Convert.ToDateTime(rowItem.Where(Of FL)(Function(s, t) s.Val = "Last Activity Time").[Select](Function(x) x.Content).[Single]())
        Catch
        End Try
        ListBox1.Items.Add(loContact.FirstName + " " + loContact.LastName)
        loContactList.Add(loContact)
    Next
End Sub
End Class
Public Class Contact
<JsonProperty(PropertyName:="CONTACTID")>
Public Property ContactID() As String
    Get
        Return m_ContactID
    End Get
    Set
        m_ContactID = Value
    End Set
End Property
Private m_ContactID As String
<JsonProperty(PropertyName:="SMOWNERID")>
Public Property OwnerID() As String
    Get
        Return m_OwnerID
    End Get
    Set
        m_OwnerID = Value
    End Set
End Property
Private m_OwnerID As String
<JsonProperty(PropertyName:="Contact Owner")>
Public Property ContactOwner() As String
    Get
        Return m_ContactOwner
    End Get
    Set
        m_ContactOwner = Value
    End Set
End Property
Private m_ContactOwner As String
<JsonProperty(PropertyName:="First Name")>
Public Property FirstName() As String
    Get
        Return m_FirstName
    End Get
    Set
        m_FirstName = Value
    End Set
End Property
Private m_FirstName As String
<JsonProperty(PropertyName:="Last Name")>
Public Property LastName() As String
    Get
        Return m_LastName
    End Get
    Set
        m_LastName = Value
    End Set
End Property
Private m_LastName As String
<JsonProperty(PropertyName:="Email")>
Public Property Email() As String
    Get
        Return m_Email
    End Get
    Set
        m_Email = Value
    End Set
End Property
Private m_Email As String
<JsonProperty(PropertyName:="SMCREATORID")>
Public Property CreatorID() As String
    Get
        Return m_CreatorID
    End Get
    Set
        m_CreatorID = Value
    End Set
End Property
Private m_CreatorID As String
<JsonProperty(PropertyName:="Created By")>
Public Property CreatedBy() As String
    Get
        Return m_CreatedBy
    End Get
    Set
        m_CreatedBy = Value
    End Set
End Property
Private m_CreatedBy As String
<JsonProperty(PropertyName:="MODIFIEDBY")>
Public Property ModifiedByID() As String
    Get
        Return m_ModifiedByID
    End Get
    Set
        m_ModifiedByID = Value
    End Set
End Property
Private m_ModifiedByID As String
<JsonProperty(PropertyName:="Modified By")>
Public Property ModifiedBy() As String
    Get
        Return m_ModifiedBy
    End Get
    Set
        m_ModifiedBy = Value
    End Set
End Property
Private m_ModifiedBy As String
<JsonProperty(PropertyName:="Created Time")>
Public Property CreatedTime() As DateTime
    Get
        Return m_CreatedTime
    End Get
    Set
        m_CreatedTime = Value
    End Set
End Property
Private m_CreatedTime As DateTime
<JsonProperty(PropertyName:="Modified Time")>
Public Property ModifiedTime() As DateTime
    Get
        Return m_ModifiedTime
    End Get
    Set
        m_ModifiedTime = Value
    End Set
End Property
Private m_ModifiedTime As DateTime
<JsonProperty(PropertyName:="Last Activity Time")>
Public Property LastActivityTime() As DateTime
    Get
        Return m_LastActivityTime
    End Get
    Set
        m_LastActivityTime = Value
    End Set
End Property
Private m_LastActivityTime As DateTime
End Class


Public Class ResponseActual

<JsonProperty("response")>
Public Property Response() As Response2
    Get
        Return m_Response
    End Get
    Set
        m_Response = Value
    End Set
End Property
Private m_Response As Response2
End Class

Public Class Response2

<JsonProperty("result")>
Public Property Result() As Result
    Get
        Return m_Result
    End Get
    Set
        m_Result = Value
    End Set
End Property
Private m_Result As Result

<JsonProperty("uri")>
Public Property Uri() As String
    Get
        Return m_Uri
    End Get
    Set
        m_Uri = Value
    End Set
End Property
Private m_Uri As String
End Class

Public Class Result

<JsonProperty("Contacts")>
Public Property Contacts() As Contacts
    Get
        Return m_Contacts
    End Get
    Set
        m_Contacts = Value
    End Set
End Property
Private m_Contacts As Contacts
End Class

Public Class Contacts

<JsonProperty("row")>
Public Property Row() As IList(Of Row)
    Get
        Return m_Row
    End Get
    Set
        m_Row = Value
    End Set
End Property
Private m_Row As IList(Of Row)
End Class

Public Class Row

<JsonProperty("no")>
Public Property No() As String
    Get
        Return m_No
    End Get
    Set
        m_No = Value
    End Set
End Property
Private m_No As String

<JsonProperty("FL")>
Public Property FL() As IList(Of FL)
    Get
        Return m_FL
    End Get
    Set
        m_FL = Value
    End Set
End Property
Private m_FL As IList(Of FL)
End Class

Public Class FL

<JsonProperty("content")>
Public Property Content() As String
    Get
        Return m_Content
    End Get
    Set
        m_Content = Value
    End Set
End Property
Private m_Content As String

<JsonProperty("val")>
Public Property Val() As String
    Get
        Return m_Val
    End Get
    Set
        m_Val = Value
    End Set
End Property
Private m_Val As String
End Class

Я застреваю в этой строке: для каждой строки var In respone.Response.Result.Contacts.Row

Я знаю, что у меня не может быть var из С#, но я не могу понять, как это сделать.


person Graham Ballard    schedule 01.12.2016    source источник
comment
просто удалите var, тогда все должно работать. Если нет, убедитесь, что Option Infer On верно для вашего файла кода/проекта.   -  person Alex B.    schedule 01.12.2016


Ответы (1)


Код, который у вас есть, можно значительно упростить. С классами JSON все в порядке, за одним исключением:

Public Class Row
    Public Property no As String
    Public Property FL As FL()
End Class

Поскольку это фиксировано, массив будет работать нормально.

Но класс контакта можно изменить, чтобы сделать часть работы за вас:

Public Class Contact
    Public Property ContactID As String
    Public Property OwnerID As String
    Public Property ContactOwner As String
    Public Property FirstName As String
    Public Property LastName As String
    Public Property Email As String
    Public Property CreatorID As String
    Public Property CreatedBy As String
    Public Property ModifiedByID As String
    Public Property ModifiedBy As String
    Public Property CreatedTime As DateTime
    Public Property ModifiedTime As DateTime
    Public Property LastActivityTime As DateTime

    Public Sub New(items As FL())

        ContactID = GetValue("CONTACTID", items)
        ContactOwner = GetValue("SMOWNERID", items)
        FirstName = GetValue("First Name", items)
        LastName = GetValue("Last Name", items)
        ...
        Dim tmp = GetValue("Created Time", items)
        CreatedTime = Convert.ToDateTime(tmp)

        tmp = GetValue("Modified Time", items)
        ModifiedTime = Convert.ToDateTime(tmp)

    End Sub

    ' the key corresponds to `val` in the json
    Private Function GetValue(key As String, items As FL()) As String
        Dim value = items.FirstOrDefault(Function(q) q.val = key)
        If value Is Nothing Then
            Return ""
        Else
            Return value.content
        End If
    End Function

    Public Overrides Function ToString() As String
        Return String.Format("{0}, {1}", LastName, FirstName)
    End Function
End Class
  • AutoProperites используются для сокращения утомительного шаблонного кода.
  • Конструктор принимает FL() и использует его для самостоятельного поиска значений реквизита.
  • Вспомогательная функция GetValue() выполняет фактический поиск, поэтому вы не повторяетесь
  • Списанные методы linq были немного... грубыми. Небольшая проверка предотвращает появление всех этих пустых блоков Try/Catch.
  • Переопределение ToString() обеспечивает отображение ListBox, созданный список используется как DataSource, поэтому вам не нужно делать копии битов данных для элемента управления.

Кроме того, я не уверен, что сопоставление свойств, которое вы хотели использовать, правильное. Например, CONTACTID и Contact Owner кажутся перепутанными, и для некоторых вещей я не могу сказать, откуда они должны браться, например SMCREATORID.

Применение:

' form/class level list
Private contacts As List(Of Contact)

В другом месте:

' using NEW here, empties the list from previous runs
contacts = New List(Of Contact)

Dim jstr = ...the json from whereever ...
Dim jobj = JsonConvert.DeserializeObject(Of ResponseActual)(jstr)

For Each r As Row In jobj.response.result.Contacts.row
    ' each contact item creates itself
    ' from the FL array
    contacts.Add(New Contact(r.FL))
Next

ListBox1.DataSource = contacts
person Ňɏssa Pøngjǣrdenlarp    schedule 01.12.2016
comment
Большое спасибо за Вашу помощь! Я получаю сообщение об ошибке. Произошло необработанное исключение типа «System.InvalidCastException» в WindowsApplication1.exe. Дополнительная информация: невозможно привести объект типа «System.Collections.Generic.List`1[WindowsApplication1.FL]» к типу «WindowsApplication1». .FL[]'. вконтакты.Добавить(Новый контакт(r.FL)) - person Graham Ballard; 01.12.2016
comment
Извините, свойство FL в свойстве класса Row: Public Property FL As FL() вы не добавляете/удаляете из него, поэтому оно не обязательно должно быть IList массив подойдет. Вы также можете просто нажать .ToArray() на вызове нового контакта, чтобы он заработал. - person Ňɏssa Pøngjǣrdenlarp; 01.12.2016
comment
Круто, это сработало! Не приведет ли переопределение к тому, что я не смогу работать с другими полями? Перечисленные — это только пример, их гораздо больше, и мне нужно работать со всеми ними. Например, я добавил электронную почту, но она выдает ошибку. Необработанное исключение типа «System.NullReferenceException» произошло в WindowsApplication1.exe. Дополнительная информация: Ссылка на объект не указывает на экземпляр объекта. когда он достигает записи с пустым адресом электронной почты на Dim value = items.FirstOrDefault(Function(q) q.val = key).content - person Graham Ballard; 01.12.2016
comment
Я ответил на свой вопрос о переопределении. Все еще есть ошибка, когда поле пусто, хотя - person Graham Ballard; 01.12.2016
comment
a) вы по-прежнему можете использовать другие свойства (не поля) как обычно b) Ack - меня слишком смутило название, чтобы сопоставить все свойства... см. (действительно) небольшое изменение в GetValue(), чтобы учесть отсутствующие данные - не могу получить содержимое нулевого объекта. - person Ňɏssa Pøngjǣrdenlarp; 01.12.2016