如何正确反序列化来自 JIRA webhook 的评论

How to deserialize comments from JIRA webhook correctly

我目前正在从 JIRA 反序列化 Webhook URL,但我在反序列化 MVC 应用程序中控制器中问题的注释部分时遇到了问题。

目前我正在正确反序列化除 Json 负载的注释部分之外的所有内容。

这是评论在 JSON 负载中的样子的视图:

'comments':[
{'id':'71980','displayName':'Ciaran','active':true},'created':'2015-06-10T09:30:07.983+0100','updated':'2015-06-10T09:30:07.983+0100'},
{'id':'72026','displayName':'Ciaran ','active':true},'created':'2015-06-10T14:50:34.253+0100','updated':'2015-06-10T14:50:34.253+0100'}]

使用 Json2CSharp,然后复制我需要的 类,评论如下所示:

然后 类 看起来像这样:

Public Class Rootobject
     Public Property expand As String
     Public Property id As String
     Public Property self As String
     Public Property key As String
     Public Property fields As Fields
End Class     

Public Class Fields
     Public Property comment As Comment
End Class

Public Class Comment
     Public Property startAt As Integer
     Public Property maxResults As Integer
     Public Property total As Integer
     Public Property comments As List(Of Comment2)
End Class

Public Class Comment2
     Public Property body As String
     Public Property created As Date
     Public Property updated As Date
End Class

我不确定如何正确反序列化我试过这样做:

Dim reader As System.IO.StreamReader = New System.IO.StreamReader(HttpContext.Request.InputStream)
Dim rawSendGridJSON As String = reader.ReadToEnd()
Dim issue As Rootobject = JsonConvert.DeserializeObject(Of Rootobject)(rawSendGridJSON)

这适用于除评论之外的所有其他内容,我收到此错误消息:

无法将当前 JSON 数组(例如 [1,2,3])反序列化为类型 'class.Comment1',因为该类型需要一个 JSON 对象(例如){"name":"value"}) 正确反序列化。

我应该如何正确反序列化它?

rootObject Json 看起来像这样:

"expand":"renderedFields,names,schema,transitions,operations,editmeta,changelog,
"id": "41948",
"self": "http://jira:8080/rest/api/latest/issue/41948",
"key": "OP-155",
"fields": {
        "comment": {
        "startAt": 0,
        "maxResults": 9,
        "total": 9,
        "comments": []
                   } 
          }

我可以从 rootObject 成功获取 ID 或密钥,但在 "fields" 部分获取注释时会出现错误。但我可以从 "fields" 部分获取信息,例如我可以显示摘要或已创建。

评论数量的问题,例如有 9 个,我反序列化的方式处理这个问题是不正确的。


尝试 this link 问题出在评论上,其中包含 json 已验证的 paylaod

由于提供的 "JSON" 字符串无效,并且假设您对此无能为力,您始终可以使用 String.Split(regex) 方法快速处理它,并且使用替换方法清除非转义控制字符,如 [、{、'、":例如 String.Replace("[", "")。

因此您可以创建一个包含与评论相关的所有信息的 CommentInfo class,并使函数 return 成为 class.

的填充实例

commentary link中提供的json与问题中的class不匹配。例如,您的 RootObject class 根本不匹配容器,而是主要是 Issue class 除了 "expand" 属性 :

{
"timestamp": 1437140952183,
"webhookEvent": "jira:issue_updated",
"user": {
    ...
  ,
    "displayName": "Ciaran",
    "active": true,
    "timeZone": "Europe/London"
},
"issue": {...
 },
"comment": {...
}...

基于 jsfiddle json,根目录(可以重命名)应定义为:

Public Class CiaranObj
    Public Property timestamp As Long
    Public Property webhookEvent As String
    Public Property user As Actor
    Public Property issue As Issue
    Public Property comment As CommentItem
End Class

重要说明:提供的 jsfiddle 示例可能完整也可能不完整。在各种 classes 中有许多未定义的类型。 Fields 例如有几个类型为空导致:

Property customfield_10070 As Object
当存在数据时,

Object 可能不是最佳类型。同样,TimeTracking 完全未定义。

显然,您对评论不感兴趣。如果为真,您可以只解析 json。如果您在 jsonlint.com 之类的格式中查看格式化的 json,您可以看到其中的关系。所以,只是为了获得评论:

Dim jstr =  ' from whereever

' extract comments to reduce typing and typos
Dim comments = myJ("issue")("fields")("comment")
' get the comment count
Dim CommentCount = Convert.ToInt32(comments("maxResults"))
'print them
For n As Int32 = 0 To CommentCount - 1
    Console.WriteLine("ID: {0}, Created: {1} upd Author: {2}",
                      comments("comments")(n)("id").ToString,
                      comments("comments")(n)("created").ToString,
                      comments("comments")(n)("author")("displayName").ToString)
Next

输出:

ID: 72430, Created: 6/16/2015 8:48:52 AM upd Author: Ciaran ID: 72431, Created: 6/16/2015 9:02:16 AM upd Author: Ciaran ID: 72661, Created: 6/18/2015 9:58:12 AM upd Author: Ciaran

您可能已经在格式化的 JsonLint 显示中注意到,注释实际上比根隐藏得更深。可能还有其他一些类似上面的处理,但是没有提到。

要反序列化为对象,您需要使用 classes。您可以删除任何您不关心的属性,但不能将属性从一个 class 迁移到另一个。使用任何机器人——json2csharp、jsonutils.com1 会创建 VB classes 甚至 Visual Studio 2012 或更高版本(Edit - Paste Special - Paste as Json Classes -- 要自动创建 classes,您可能需要花点时间 "normalize" classes。

  • User class 一遍又一遍地重复 UserAssigneeCreator 等。我将其简化为一种类型(Class) 命名为 Actor.
  • AvatarUrls 也像 AvatarUrls1 一样一遍又一遍地重复。你只需要一种类型。
  • 有一个 Comment 输入 Fields
  • Comment还包括评论项合集,我把这些改名为CommentItem
  • CommentItem 也用于根对象,但机器人会称它为 Comment2 这是您在第一个 json 代码段中显示的
  • comments属性可以定义为数组或者List<T>如图

请记住,您可以删除任何您不关心的 属性(但您不能移动或简单地重命名它们)。我做的:

Public Class CiaranObj
    Public Property timestamp As Long
    Public Property webhookEvent As String
    Public Property user As Actor
    Public Property issue As Issue
    Public Property comment As CommentItem
End Class

Public Class Actor
    Public Property self As String
    Public Property name As String
    Public Property key As String
    Public Property emailAddress As String
    Public Property avatarUrls As Avatarurls
    Public Property displayName As String
    Public Property active As Boolean
    Public Property timeZone As String
End Class

Public Class Avatarurls
    ' provide property mapping for illgal names
    <JsonProperty("48x48")>
    Public Property _48x48 As String
    <JsonProperty("24x24")>
    Public Property _24x24 As String
    <JsonProperty("16x16")>
    Public Property _16x16 As String
    <JsonProperty("32x32")>
    Public Property _32x32 As String
End Class

Public Class Issue
    Public Property id As String
    Public Property self As String
    Public Property key As String
    Public Property fields As Fields
End Class

Public Class Fields
    'Public Property issuetype As Issuetype         ' not shown
    ' ...
    Public Property summary As String
    Public Property creator As Actor

    Public Property reporter As Actor
    Public Property progress As Progress        ' not shown
    Public Property comment As Comment
End Class

Public Class Comment
    Public Property startAt As Integer
    Public Property maxResults As Integer
    Public Property total As Integer
    Public Property comments As CommentItem()
    ' or:
    'Public Property comments As List(of CommentItem)
End Class

Public Class CommentItem
    Public Property self As String
    Public Property id As String
    Public Property author As Actor
    Public Property body As String
    Public Property updateAuthor As Actor
    Public Property created As DateTime
    Public Property updated As DateTime
End Class

哇!现在,您可以反序列化为 CiaranObj 对象:

Dim jstr =  ...from whereever
Dim complexJ = JsonConvert.DeserializeObject(Of CiaranObj)(jstr)

' reduce typing
Dim c As Comment = complexJ.issue.fields.comment

For n As Int32 = 0 To c.maxResults - 1
    Console.WriteLine("ID: {0}, Created: {1} upd Author: {2}",
                      c.comments(n).id.ToString,
                      c.comments(n).created.ToString,
                      c.comments(n).author.displayName)
Next

它打印相同的信息。

同样,这在评论中提供的 jsfiddle 上运行良好。它显然已经过清理,在此过程中,可能已经进行了其他更改(例如丢失的 "expand")。

1 jsonutils.com 很酷,因为它可以创建 VB classes,但它实际上在这上面耗尽了动力json:生成的classes不完整。这显然是由于大小。