将JSON键与类字段不精确地匹配

本文关键字:不精确 字段 JSON | 更新日期: 2023-09-27 17:59:29

我正在尝试将JSON流反序列化为VB.NET对象。然而,每当我试图将值分配给对象中的字段时,其中一个字段都不会编译,因为JSON字段包含连字符,据我所知,我需要将字段名和JSON键名完全匹配。这是JSON:的一个例子

{
    "email":"john.doe@sendgrid.com",
    "sg_event_id":"VzcPxPv7SdWvUugt-xKymw",
    "sg_message_id":"142d9f3f351.7618.254f56.filter-147.22649.52A663508.0",
    "timestamp":1386636112,
    "smtp-id":"<142d9f3f351.7618.254f56@sendgrid.com>",
    "event":"processed",
    "category":["category1","category2","category3"],
    "id":"001","purchase":"PO1452297845","uid":"123456"
}

这个JSON示例来自一个测试流(通过POST)到一个设计用于与SendGrid的EventWebhookneneneba API通信的webhook(https://sendgrid.com/docs/API_Reference/Webhooks/event.html)

我有一个JSON被分配给的类,如下所示:

Partial Class SendGridEvent
    Public email As String
    Public sg_event_id As String
    Public sg_message_id As String
    Public timestamp As String
    Public smtp-id As String
    Public [event] As String
    Public category() As String
    Public id As String
    Public purchase As String
    Public uid As String
    Public reason As String
    Public ip As String
    Public useragent As String
    Public url As String
    Public status As String
    Public type As String
End Class

我已经成功地获得了除了一个(smtp-id)之外的所有字段,以便在流通过时正确分配。这样就完成了(忽略列表声明,SendGrid批量发送电子邮件信息,但我担心它会使示例更加混乱):

' Create new stream reader to take in serialized JSON from SendGrid
Dim oSR = New StreamReader(Request.InputStream)
' Store entire stream in new String variable called sContent
Dim sContent As String = oSR.ReadToEnd()
' Declare a new list of SendGridEvent objects
Dim masterOutput = New List(Of SendGridEvent)
' Declare new SendGridEvent objects within the list called masterOutput
Dim a = New SendGridEvent
Dim b = New SendGridEvent
Dim c = New SendGridEvent
Dim d = New SendGridEvent
' Assign individual SendGridEvent object just created to the list of SendGridEvents
masterOutput.Add(a)
masterOutput.Add(b)
masterOutput.Add(c)
masterOutput.Add(d)
' Assign the deserialized JSON String to the BulkEmail array named output, via BulkEmail array deserialization
Dim res = JsonConvert.DeserializeObject(Of List(Of SendGridEvent))(sContent)
' Declare String to use in For Each loop
Dim sContentPair As String = ""
' Write the info from each SendGridEvent in the master SendGridEvent list (masterOutput) to the variable sContentPair
For Each data As SendGridEvent In res
    sContentPair = sContentPair + " => " + data.email + " => " + data.sg_event_id + " => " + data.sg_message_id + _
        " => " + data.timestamp + " => " + data.smtp-id + " => " + data.event + " => " + data.category(0) + " => " + data.id _
    + " => " + data.purchase + " => " + data.uid + " => " + data.reason + " => " + data.ip + " => " + data.useragent _
    + " => " + data.url + " => " + data.status + " => " + data.status + " => " + data.type + " STOP "
Next

使用上面的JSON示例流,这就是输出(我为不整洁的格式道歉):

=> john.doe@sendgrid.com => VzcPxPv7SdWvUugt-xKymw => 
142d9f3f351.7618.254f56.filter-147.22649.52A663508.0 => 1386636112 => 
=> processed => category1 => 001 => PO1452297845 => 123456 => => => 
=> => => => STOP

SendGridEvent类中的属性smtp-id不会编译,因为连字符结束了标识符声明。因此,JSON流中的smtp-id字段不能将自己分配给对象中的属性。我曾尝试使用字段名称smtp_002D_id来强制在字段名称中使用连字符(因此我设法获得示例输出,否则程序不会编译),但正如您所看到的,随后没有分配任何值。

我浏览了50多个网页和几本书,找到了解决这个普遍问题的方法。除了你在这里看到的之外,我对序列化/反序列化并不熟悉,而且我还没有找到一个很好的参考,来了解如何将值分配给类属性(属性名称是否需要与JSON密钥名称完全匹配,是否需要按照流吐出的确切顺序,等等)

下面的答案

多亏了蒂姆和胡安,解决方案相当迅速。将JsonProperty属性附加到字段可以将JSON流正确地分配给正确的属性。更正了以下代码:

Partial Class SendGridEvent
    <JsonProperty("email")>
    Public Email As String
    <JsonProperty("sg_event_id")>
    Public SgEventId As String
    <JsonProperty("sg_message_id")>
    Public SgMessageId As String
    <JsonProperty("timestamp")>
    Public Timestamp As String
    <JsonProperty("smtp-id")>
    Public SmtpId As String
    <JsonProperty("event")>
    Public EmailEvent As String
    <JsonProperty("category")>
    Public Category() As String
    <JsonProperty("id")>
    Public Id As String
    <JsonProperty("purchase")>
    Public Purchase As String
    <JsonProperty("uid")>
    Public UId As String
    <JsonProperty("reason")>
    Public Reason As String
    <JsonProperty("ip")>
    Public Ip As String
    <JsonProperty("useragent")>
    Public UserAgent As String
    <JsonProperty("url")>
    Public Url As String
    <JsonProperty("status")>
    Public Status As String
    <JsonProperty("type")>
    Public Type As String
End Class

将JSON键与类字段不精确地匹配

您应该使用JsonProperty属性来让Json。NET知道smtp-id映射到您的领域。

Partial Class SendGridEvent
    Public email As String
    Public sg_event_id As String
    Public sg_message_id As String
    Public timestamp As String
    <JsonProperty("smtp-id")>
    Public smtp_id As String
    Public [event] As String
    ...

如果这有助于代码更清晰,您可能还想将其用于其他字段。例如,您可能应该为event字段选择一个非关键字名称,并且您可能希望遵循。NET标准的PascalCase而不是JSON风格的under_scores(例如SgEventId而不是sg_event_id)。

此外,这些应该(几乎可以肯定)都是属性,而不是字段。

我曾经遇到过这个问题,在这种情况下,我只是将smtp-id替换为smtpid,然后进行序列化。

将类属性更改为smtpid,一切都必须正常。

根据蒂姆的回答,我想出了这门课,并进行了测试和作业。您需要使用Newtonsoft进行添加。Json;

     public class DataClass
            {
                public string email { get; set; }
                public string sg_event_id { get; set; }
                public string sg_message_id { get; set; }
                public int timestamp { get; set; }
                 [JsonProperty("smtp-id")]
                public string smtp { get; set; }
                 [JsonProperty("event")]
                   public string eve { get; set; }
                public List<string> category { get; set; }
                public string id { get; set; }
                public string purchase { get; set; }
                public string uid { get; set; }
            }

This code is from a console app test:

               string json = "{";
    json += "'"email'":'"john.doe@sendgrid.com'"" + ",";
    json +="'"sg_event_id'":'"VzcPxPv7SdWvUugt-xKymw'"" + "," ;
    json += "'"sg_message_id'":'"142d9f3f351.7618.254f56.filter-147.22649.52A663508.0'"" + ",";
   json += "'"timestamp'":1386636112" + ",";
   json += "'"smtp-id'":'"<142d9f3f351.7618.254f56@sendgrid.com>'"" + ",";
   json += "'"event'":'"processed'"" + ",";
   json += "'"category'":['"category1'",'"category2'",'"category3'"]" + ",";
   json += "'"id'":'"001'",'"purchase'":'"PO1452297845'",'"uid'":'"123456'"" ;
   json +="}";
            DataClass data = JsonConvert.DeserializeObject<DataClass>(json);
            Console.Read();