Как десериализовать более сложный документ Json в Vb.net с помощью Newtonsoft

#json #vb.net #json.net

#json #vb.net #json.net

Вопрос:

У меня есть rest API, который возвращает мне ответ json, представляющий собой массив документов, который, в свою очередь, имеет несколько массивов сам по себе. Ниже приведен пример документа, который я хотел бы десериализовать

 {
             "DocId": "contact::6f128681-218d-409d-b71d-31031852057d",
             "Name": "Joe F Miller",
             "buckets": [
                {
                     "DocId": "leadbucket::5652A756-5B58-45A5-9566-9C85E8783440",
                     "text": "Dead Leads"
                },
                {
                     "DocId": "leadbucket::8A234FC1-6389-485D-8BDE-7FCB1E7639E0",
                     "text": "No Follow-Up Needed"
                },
                {
                     "DocId": "leadbucket::C97632BE-5A24-4AE7-8D18-4DFE174F0D0F",
                     "text": "Long-Term Buyers"
                },
                {
                     "DocId": "leadbucket::D6802064-8AC5-4E5A-855E-B59C32859C81",
                     "text": "New Lead"
                }
            ],
             "emails": [
                {
                     "other": "demo@test.com"
                },
                {
                     "work": "work@demo.com"
                },
                {
                     "work": "work2@demo.com"
                }
            ],
             "followup": {
                 "date": "05/01/2019",
                 "type": "phone"
            },
             "lastactivity": "04/05/2019",
             "phones": [
                {
                     "home": "(213) 444-2222"
                },
                {
                     "work": "(949) 555-1212"
                }
            ],
             "tags": [
                {
                     "DocId": "tag::FC276FBD-DC3A-4E18-8244-E89EF24E022E",
                     "text": "Buyer"
                },
                {
                     "DocId": "tag::EA5DE0FB-34B0-4F7C-B631-177D6BD2F65E",
                     "text": "Investor"
                }
            ]
        }
  

После того, как я получу ответ от моего API, я использую приведенный ниже код, чтобы попытаться преобразовать данные.

 ContactList = JsonConvert.DeserializeObject(Of List(Of Contact.ContactList))(read.Item("Data").ToString)
  

Итак, я надеюсь, что кто-нибудь сможет указать мне правильное направление в том, как создать класс для хранения документов такого типа и как его десериализовать. Должен ли я делать это в своем классе или мне нужно вызывать десериализацию для каждого массива в Json?

Еще одна проблема, с которой я сталкиваюсь, — это раздел электронных писем и телефонов, поскольку значение ключа не уникально, и я не всегда знаю, что будет возвращено. как бы я создал класс для хранения этого, поскольку ключевое поле может измениться.

Комментарии:

1. Попробуйте json2csharp.com , он сгенерирует правильную структуру классов для десериализации JSON в

2. Как и где я мог бы реализовать IEnumerable(словаря (строки, String)) ? я бы предположил, что я бы поместил его в класс, который определяет данные для этого. Я смог определить сегменты и теги, которые я создал в своем классе, в виде списка (тегов)

Ответ №1:

Пример, использование IEnumerable(Of Dictionary(Of String, String)) для десериализации объектов JSON, которые имеют неопределенное количество элементов, с неопределенной комбинацией пар (ключ, значение) для каждого объекта.
Ключевая часть также может повторяться, как показано в примере:

  "emails": [
    {"other": "demo@test.com"},
    {"work": "work@demo.com"},
    {"work": "work2@demo.com"}
  

other , work Ключи могут отличаться каждый раз и могут повторяться.

Десериализация / сериализация этого свойства с помощью IEnumerable(Of Dictionary(Of String, String)) , позволяет

Пример объекта класса Contacts содержит методы (упрощенные здесь), которые выполняют десериализацию объекта JSON и сериализацию корня объекта, воспроизводя исходный объект JSON.

Эти методы являются статическими (совместно используемыми), вам просто нужно вызвать метод, нет необходимости создавать экземпляр класса Contacts.
Например, десериализовать объект JSON (строку, полученную от службы):

 Dim myContacts As Contacts.RootObject = Contacts.DeserializeJSON(JSONObject)
  

Сериализуйте объект класса обратно в исходную строку:

 Dim myJsonContacts = Contacts.SerializeJSON(myContacts)
  

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

Перечислите все электронные письма и номера телефонов в десериализованном объекте класса:
(просто пример: преобразование в список не требуется)

 myContacts.Emails.ToList().ForEach(
    Sub(em) Console.WriteLine($"from: {em.Keys(0)}, Email: {em.Values(0)}"))

myContacts.Phones.ToList().ForEach(
    Sub(ph) Console.WriteLine($"place: {ph.Keys(0)}, Phone Number: {ph.Values(0)}"))
  

Доступ к одному электронному письму (или номеру телефона):
(конечно, можно использовать любой другой метод извлечения (Key, Value) пары из словаря)

 Dim eMailFrom = myContacts.Emails(0).Keys(0)
Dim eMailValue = myContacts.Emails(0).Values(0)
  

Получите все электронные письма из определенного места ( work , здесь):

 Dim emailFromWork = myContacts.Emails.Where(Function(em) em.Keys.Contains("work"))
  

Contacts Класс:
Некоторые свойства украшены <JsonProperty()> . Имя свойства изменено, потому что исходный JSON использует имена, которые являются зарезервированными ключевыми словами в языке.

Например:

<JsonProperty("text")>
Public Property BucketText As String

 Imports Newtonsoft.Json

Public Class Contacts

    Public Shared Function DeserializeJSON(JsonObject As String) As RootObject
        Return JsonConvert.DeserializeObject(Of RootObject)(JsonObject)
    End Function

    Public Shared Function SerializeJSON(classObject As RootObject) As String
        Return JsonConvert.SerializeObject(classObject)
    End Function

    Partial Public Class RootObject
        Public Property DocId As String
        Public Property Name As String
        Public Property Buckets As List(Of Bucket)
        Public Property Emails As Dictionary(Of String, String)()
        Public Property Followup As Followup
        Public Property Lastactivity As String
        Public Property Phones As IEnumerable(Of Dictionary(Of String, String))
        Public Property Tags As List(Of Tag)
    End Class

    Partial Public Class Bucket
        Public Property DocId As String
        <JsonProperty("text")>
        Public Property BucketText As String
    End Class

    Partial Public Class Tag
        Public Property DocId As String
        <JsonProperty("text")>
        Public Property TagText As String
    End Class

    Partial Public Class Followup
        <JsonProperty("date")>
        Public Property FollowupDate As String

        <JsonProperty("type")>
        Public Property FollowupType As String
    End Class
End Class