解析 Jira Abhook 评论

Parsing JIRA webhook comments

我正在尝试正确解析 JIRA webhook 评论部分。现在,以下代码适用于第一个评论:

data = request.json
jira_comment = data['issue']['fields']['comment']['comments'][0].get('body')

但是,每次触发新的 webhook 时,例如添加新评论,我只能收到 JSON 消息中的第一条评论。如果我能以某种方式从另一个评论中识别出每条评论,或者只解析问题的最后一条评论。什么是最好的方法,或者它甚至可能因为 JIRA webhook JSON 看起来坏了(多个 'body' 键)。

请参阅下面的 JSON 数据,要使其更清晰,请使用此 http://jsbeautifier.org/:

{
    "timestamp": 1443024903340,
    "webhookEvent": "jira:issue_updated",
    "user": {
        "self": "http://192.168.10.58:8080/rest/api/2/user?username=jhdoe",
        "name": "jhdoe",
        "key": "jhdoe",
        "emailAddress": "john.doe@corp.com",
        "avatarUrls": {
            "48x48": "http://www.gravatar.com/avatar/f94b6b6c15d155f4d4b3b2c05509ab0a?d=mm&s=48",
            "24x24": "http://www.gravatar.com/avatar/f94b6b6c15d155f4d4b3b2c05509ab0a?d=mm&s=24",
            "16x16": "http://www.gravatar.com/avatar/f94b6b6c15d155f4d4b3b2c05509ab0a?d=mm&s=16",
            "32x32": "http://www.gravatar.com/avatar/f94b6b6c15d155f4d4b3b2c05509ab0a?d=mm&s=32"
        },
        "displayName": "John Doe",
        "active": true,
        "timeZone": "Europe/Berlin"
    },
    "issue": {
        "id": "10300",
        "self": "http://192.168.10.58:8080/rest/api/2/issue/10300",
        "key": "DEMO-6",
        "fields": {
            "issuetype": {
                "self": "http://192.168.10.58:8080/rest/api/2/issuetype/3",
                "id": "3",
                "description": "A task that needs to be done.",
                "iconUrl": "http://192.168.10.58:8080/images/icons/issuetypes/task.png",
                "name": "Task",
                "subtask": false
            },
            "components": [],
            "timespent": null,
            "timeoriginalestimate": null,
            "description": "Hey",
            "project": {
                "self": "http://192.168.10.58:8080/rest/api/2/project/10000",
                "id": "10000",
                "key": "DEMO",
                "name": "DEMO",
                "avatarUrls": {
                    "48x48": "http://192.168.10.58:8080/secure/projectavatar?avatarId=10011",
                    "24x24": "http://192.168.10.58:8080/secure/projectavatar?size=small&avatarId=10011",
                    "16x16": "http://192.168.10.58:8080/secure/projectavatar?size=xsmall&avatarId=10011",
                    "32x32": "http://192.168.10.58:8080/secure/projectavatar?size=medium&avatarId=10011"
                }
            },
            "fixVersions": [],
            "aggregatetimespent": null,
            "resolution": null,
            "timetracking": {},
            "customfield_10006": null,
            "attachment": [],
            "customfield_10009": "0|i0000f:",
            "aggregatetimeestimate": null,
            "resolutiondate": null,
            "workratio": -1,
            "summary": "Comment test",
            "lastViewed": "2015-09-23T19:14:11.979+0300",
            "watches": {
                "self": "http://192.168.10.58:8080/rest/api/2/issue/DEMO-6/watchers",
                "watchCount": 1,
                "isWatching": true
            },
            "creator": {
                "self": "http://192.168.10.58:8080/rest/api/2/user?username=jhdoe",
                "name": "jhdoe",
                "key": "jhdoe",
                "emailAddress": "john.doe@corp.com",
                "avatarUrls": {
                    "48x48": "http://www.gravatar.com/avatar/f94b6b6c15d155f4d4b3b2c05509ab0a?d=mm&s=48",
                    "24x24": "http://www.gravatar.com/avatar/f94b6b6c15d155f4d4b3b2c05509ab0a?d=mm&s=24",
                    "16x16": "http://www.gravatar.com/avatar/f94b6b6c15d155f4d4b3b2c05509ab0a?d=mm&s=16",
                    "32x32": "http://www.gravatar.com/avatar/f94b6b6c15d155f4d4b3b2c05509ab0a?d=mm&s=32"
                },
                "displayName": "John Doe",
                "active": true,
                "timeZone": "Europe/Berlin"
            },
            "subtasks": [],
            "created": "2015-09-21T17:39:14.518+0300",
            "reporter": {
                "self": "http://192.168.10.58:8080/rest/api/2/user?username=jhdoe",
                "name": "jhdoe",
                "key": "jhdoe",
                "emailAddress": "john.doe@corp.com",
                "avatarUrls": {
                    "48x48": "http://www.gravatar.com/avatar/f94b6b6c15d155f4d4b3b2c05509ab0a?d=mm&s=48",
                    "24x24": "http://www.gravatar.com/avatar/f94b6b6c15d155f4d4b3b2c05509ab0a?d=mm&s=24",
                    "16x16": "http://www.gravatar.com/avatar/f94b6b6c15d155f4d4b3b2c05509ab0a?d=mm&s=16",
                    "32x32": "http://www.gravatar.com/avatar/f94b6b6c15d155f4d4b3b2c05509ab0a?d=mm&s=32"
                },
                "displayName": "John Doe",
                "active": true,
                "timeZone": "Europe/Berlin"
            },
            "customfield_10000": null,
            "aggregateprogress": {
                "progress": 0,
                "total": 0
            },
            "priority": {
                "self": "http://192.168.10.58:8080/rest/api/2/priority/2",
                "iconUrl": "http://192.168.10.58:8080/images/icons/priorities/high.png",
                "name": "High",
                "id": "2"
            },
            "customfield_10001": null,
            "customfield_10100": "1234",
            "customfield_10200": null,
            "labels": [],
            "customfield_10004": null,
            "environment": null,
            "timeestimate": null,
            "aggregatetimeoriginalestimate": null,
            "versions": [],
            "duedate": null,
            "progress": {
                "progress": 0,
                "total": 0
            },
            "comment": {
                "startAt": 0,
                "maxResults": 3,
                "total": 3,
                "comments": [{
                    "self": "http://192.168.10.58:8080/rest/api/2/issue/10300/comment/10600",
                    "id": "10600",
                    "author": {
                        "self": "http://192.168.10.58:8080/rest/api/2/user?username=jhdoe",
                        "name": "jhdoe",
                        "key": "jhdoe",
                        "emailAddress": "john.doe@corp.com",
                        "avatarUrls": {
                            "48x48": "http://www.gravatar.com/avatar/f94b6b6c15d155f4d4b3b2c05509ab0a?d=mm&s=48",
                            "24x24": "http://www.gravatar.com/avatar/f94b6b6c15d155f4d4b3b2c05509ab0a?d=mm&s=24",
                            "16x16": "http://www.gravatar.com/avatar/f94b6b6c15d155f4d4b3b2c05509ab0a?d=mm&s=16",
                            "32x32": "http://www.gravatar.com/avatar/f94b6b6c15d155f4d4b3b2c05509ab0a?d=mm&s=32"
                        },
                        "displayName": "John Doe",
                        "active": true,
                        "timeZone": "Europe/Berlin"
                    },
                    "body": "Comment 1",
                    "updateAuthor": {
                        "self": "http://192.168.10.58:8080/rest/api/2/user?username=jhdoe",
                        "name": "jhdoe",
                        "key": "jhdoe",
                        "emailAddress": "john.doe@corp.com",
                        "avatarUrls": {
                            "48x48": "http://www.gravatar.com/avatar/f94b6b6c15d155f4d4b3b2c05509ab0a?d=mm&s=48",
                            "24x24": "http://www.gravatar.com/avatar/f94b6b6c15d155f4d4b3b2c05509ab0a?d=mm&s=24",
                            "16x16": "http://www.gravatar.com/avatar/f94b6b6c15d155f4d4b3b2c05509ab0a?d=mm&s=16",
                            "32x32": "http://www.gravatar.com/avatar/f94b6b6c15d155f4d4b3b2c05509ab0a?d=mm&s=32"
                        },
                        "displayName": "John Doe",
                        "active": true,
                        "timeZone": "Europe/Berlin"
                    },
                    "created": "2015-09-23T19:05:26.593+0300",
                    "updated": "2015-09-23T19:08:07.010+0300"
                }, {
                    "self": "http://192.168.10.58:8080/rest/api/2/issue/10300/comment/10601",
                    "id": "10601",
                    "author": {
                        "self": "http://192.168.10.58:8080/rest/api/2/user?username=jhdoe",
                        "name": "jhdoe",
                        "key": "jhdoe",
                        "emailAddress": "john.doe@corp.com",
                        "avatarUrls": {
                            "48x48": "http://www.gravatar.com/avatar/f94b6b6c15d155f4d4b3b2c05509ab0a?d=mm&s=48",
                            "24x24": "http://www.gravatar.com/avatar/f94b6b6c15d155f4d4b3b2c05509ab0a?d=mm&s=24",
                            "16x16": "http://www.gravatar.com/avatar/f94b6b6c15d155f4d4b3b2c05509ab0a?d=mm&s=16",
                            "32x32": "http://www.gravatar.com/avatar/f94b6b6c15d155f4d4b3b2c05509ab0a?d=mm&s=32"
                        },
                        "displayName": "John Doe",
                        "active": true,
                        "timeZone": "Europe/Berlin"
                    },
                    "body": "Comment 2",
                    "updateAuthor": {
                        "self": "http://192.168.10.58:8080/rest/api/2/user?username=jhdoe",
                        "name": "jhdoe",
                        "key": "jhdoe",
                        "emailAddress": "john.doe@corp.com",
                        "avatarUrls": {
                            "48x48": "http://www.gravatar.com/avatar/f94b6b6c15d155f4d4b3b2c05509ab0a?d=mm&s=48",
                            "24x24": "http://www.gravatar.com/avatar/f94b6b6c15d155f4d4b3b2c05509ab0a?d=mm&s=24",
                            "16x16": "http://www.gravatar.com/avatar/f94b6b6c15d155f4d4b3b2c05509ab0a?d=mm&s=16",
                            "32x32": "http://www.gravatar.com/avatar/f94b6b6c15d155f4d4b3b2c05509ab0a?d=mm&s=32"
                        },
                        "displayName": "John Doe",
                        "active": true,
                        "timeZone": "Europe/Berlin"
                    },
                    "created": "2015-09-23T19:08:13.644+0300",
                    "updated": "2015-09-23T19:08:13.644+0300"
                }, {
                    "self": "http://192.168.10.58:8080/rest/api/2/issue/10300/comment/10606",
                    "id": "10606",
                    "author": {
                        "self": "http://192.168.10.58:8080/rest/api/2/user?username=jhdoe",
                        "name": "jhdoe",
                        "key": "jhdoe",
                        "emailAddress": "john.doe@corp.com",
                        "avatarUrls": {
                            "48x48": "http://www.gravatar.com/avatar/f94b6b6c15d155f4d4b3b2c05509ab0a?d=mm&s=48",
                            "24x24": "http://www.gravatar.com/avatar/f94b6b6c15d155f4d4b3b2c05509ab0a?d=mm&s=24",
                            "16x16": "http://www.gravatar.com/avatar/f94b6b6c15d155f4d4b3b2c05509ab0a?d=mm&s=16",
                            "32x32": "http://www.gravatar.com/avatar/f94b6b6c15d155f4d4b3b2c05509ab0a?d=mm&s=32"
                        },
                        "displayName": "John Doe",
                        "active": true,
                        "timeZone": "Europe/Berlin"
                    },
                    "body": "Comment 3",
                    "updateAuthor": {
                        "self": "http://192.168.10.58:8080/rest/api/2/user?username=jhdoe",
                        "name": "jhdoe",
                        "key": "jhdoe",
                        "emailAddress": "john.doe@corp.com",
                        "avatarUrls": {
                            "48x48": "http://www.gravatar.com/avatar/f94b6b6c15d155f4d4b3b2c05509ab0a?d=mm&s=48",
                            "24x24": "http://www.gravatar.com/avatar/f94b6b6c15d155f4d4b3b2c05509ab0a?d=mm&s=24",
                            "16x16": "http://www.gravatar.com/avatar/f94b6b6c15d155f4d4b3b2c05509ab0a?d=mm&s=16",
                            "32x32": "http://www.gravatar.com/avatar/f94b6b6c15d155f4d4b3b2c05509ab0a?d=mm&s=32"
                        },
                        "displayName": "John Doe",
                        "active": true,
                        "timeZone": "Europe/Berlin"
                    },
                    "created": "2015-09-23T19:13:24.836+0300",
                    "updated": "2015-09-23T19:14:04.464+0300"
                }]
            },
            "issuelinks": [],
            "votes": {
                "self": "http://192.168.10.58:8080/rest/api/2/issue/DEMO-6/votes",
                "votes": 0,
                "hasVoted": false
            },
            "worklog": {
                "startAt": 0,
                "maxResults": 20,
                "total": 0,
                "worklogs": []
            },
            "assignee": null,
            "updated": "2015-09-23T19:15:03.338+0300",
            "status": {
                "self": "http://192.168.10.58:8080/rest/api/2/status/10000",
                "description": "",
                "iconUrl": "http://192.168.10.58:8080/images/icons/subtask.gif",
                "name": "To Do",
                "id": "10000",
                "statusCategory": {
                    "self": "http://192.168.10.58:8080/rest/api/2/statuscategory/2",
                    "id": 2,
                    "key": "new",
                    "colorName": "blue-gray",
                    "name": "To Do"
                }
            }
        }
    },
    "changelog": {
        "id": "10611",
        "items": [{
            "field": "Custom ID",
            "fieldtype": "custom",
            "from": null,
            "fromString": null,
            "to": null,
            "toString": "1234"
        }]
    }
}

好吧,您在 json 中的评论部分是一个字典列表,因此您始终可以获取列表中的最后一个,然后调用 .get('body')

jira_comment = data['issue']['fields']['comment']['comments'][-1].get('body')

这是可行的,因为在 python 中,数组索引中的负数被视为数组中的倒退。所以 -1 给你数组中的最后一项。

你的代码在没有注释的情况下能正常工作吗? 如果它不考虑检查 comments 数组的长度是否大于 0 或者只是将它包装在 try except 块中。

添加评论时,请求正文应包含 data['comment'],其中将包含触发问题更新的评论。您可以比较 data['comment']['created']data['comment']['updated'] 来判断该评论是新评论还是已编辑过。

https://developer.atlassian.com/jiradev/jira-apis/webhooks