将JSON键与类字段不匹配

时间:2015-06-23 19:27:23

标签: c# json vb.net key-value sendgrid

我正在尝试将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)到webhook,旨在与SendGrid的Event Webhook API(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

smtp-id类中的属性SendGridEvent将无法编译,因为连字符结束了标识符声明。因此,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

2 个答案:

答案 0 :(得分:1)

您应该使用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字段选择一个非关键字名称,并且您可能希望遵循PascalCase的.NET标准而不是JSON样式under_scores(例如{{1}而不是SgEventId)。

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

答案 1 :(得分:0)

我想出了这个问题,我只是在这种情况下替换为smtpid的smtp-id,然后进行序列化。

将class属性更改为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();