如何使用Newtonsoft在Vb.net中反序列化更复杂的Json Doc

时间:2019-04-22 21:32:34

标签: 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 个答案:

答案 0 :(得分: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的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