diff --git a/reviewboard/reviews/evolutions/__init__.py b/reviewboard/reviews/evolutions/__init__.py
index a9ad1e7a612a5c92cec7e9d1f962269837126662..82d15777a83483c5a300f2b697ec0e8aed75e5ac 100644
--- a/reviewboard/reviews/evolutions/__init__.py
+++ b/reviewboard/reviews/evolutions/__init__.py
@@ -11,4 +11,5 @@ SEQUENCE = [
     'default_reviewer_local_site',
     'add_issues_to_comments',
     'file_attachments',
+    'file_attachment_comment_extra_data',
 ]
diff --git a/reviewboard/reviews/evolutions/file_attachment_comment_extra_data.py b/reviewboard/reviews/evolutions/file_attachment_comment_extra_data.py
new file mode 100644
index 0000000000000000000000000000000000000000..464948663660c5cfa5fc8fd29866ed707620bee8
--- /dev/null
+++ b/reviewboard/reviews/evolutions/file_attachment_comment_extra_data.py
@@ -0,0 +1,7 @@
+from django_evolution.mutations import AddField
+from djblets.util.fields import JSONField
+
+
+MUTATIONS = [
+    AddField('FileAttachmentComment', 'extra_data', JSONField, null=True)
+]
diff --git a/reviewboard/reviews/models.py b/reviewboard/reviews/models.py
index 952a6cd497c2428c912107f146e23f932f535214..9a3c9264828106ff7e5e55d58fb031fdb85768ac 100644
--- a/reviewboard/reviews/models.py
+++ b/reviewboard/reviews/models.py
@@ -9,7 +9,8 @@ from django.utils.html import escape
 from django.utils.safestring import mark_safe
 from django.utils.translation import ugettext_lazy as _
 from djblets.util.db import ConcurrencyManager
-from djblets.util.fields import CounterField, ModificationTimestampField
+from djblets.util.fields import CounterField, JSONField, \
+                                ModificationTimestampField
 from djblets.util.misc import get_object_or_none
 from djblets.util.templatetags.djblets_images import crop_image, thumbnail
 
@@ -1504,6 +1505,7 @@ class FileAttachmentComment(BaseComment):
     file_attachment = models.ForeignKey(FileAttachment,
                                         verbose_name=_('file_attachment'),
                                         related_name="comments")
+    extra_data = JSONField(null=True)
 
     def get_file(self):
         """
diff --git a/reviewboard/webapi/resources.py b/reviewboard/webapi/resources.py
index 1c0f5de9ae684ca5ae2cd86bbb07d9ae0c02a925..331d9a5c6461728cd018c7d425ee4e6c349e8a5e 100644
--- a/reviewboard/webapi/resources.py
+++ b/reviewboard/webapi/resources.py
@@ -4516,6 +4516,11 @@ class BaseFileAttachmentCommentResource(BaseCommentResource):
             'type': 'reviewboard.webapi.resources.UserResource',
             'description': 'The user who made the comment.',
         },
+        'extra_data': {
+            'type': dict,
+            'description': 'Extra data as part of the comment. This depends '
+                           'on the type of file being commented on.',
+        },
     }, **BaseCommentResource.fields)
 
     uri_object_key = 'comment_id'
@@ -4620,9 +4625,10 @@ class ReviewFileAttachmentCommentResource(BaseFileAttachmentCommentResource):
                 'description': 'Whether the comment opens an issue.',
             },
         },
+        allow_unknown=True
     )
     def create(self, request, file_attachment_id=None, text=None,
-               issue_opened=False, *args, **kwargs):
+               issue_opened=False, extra_fields={}, *args, **kwargs):
         """Creates a file comment on a review.
 
         This will create a new comment on a file as part of a review.
@@ -4655,6 +4661,10 @@ class ReviewFileAttachmentCommentResource(BaseFileAttachmentCommentResource):
                                  text=text,
                                  issue_opened=bool(issue_opened))
 
+        for key, value in extra_fields.iteritems():
+            if value != '':
+                new_comment.extra_data[key] = value
+
         if issue_opened:
             new_comment.issue_status = BaseComment.OPEN
         else:
@@ -4687,8 +4697,9 @@ class ReviewFileAttachmentCommentResource(BaseFileAttachmentCommentResource):
                 'description': 'The status of an open issue.',
             }
         },
+        allow_unknown=True
     )
-    def update(self, request, *args, **kwargs):
+    def update(self, request, extra_fields={}, *args, **kwargs):
         """Updates a file comment.
 
         This can update the text or region of an existing comment. It
@@ -4723,6 +4734,12 @@ class ReviewFileAttachmentCommentResource(BaseFileAttachmentCommentResource):
             if value is not None:
                 setattr(file_comment, field, value)
 
+        for key, value in extra_fields.iteritems():
+            if value != '':
+                file_comment.extra_data[key] = value
+            elif key in file_comment.extra_data:
+                del file_comment.extra_data[key]
+
         file_comment.save()
 
         return 200, {
diff --git a/reviewboard/webapi/tests.py b/reviewboard/webapi/tests.py
index ca4b4ad5bde35db36eeef790b5e31ed26b064634..6f90009592d18e4a25e184aaafe52d1e90c84913 100644
--- a/reviewboard/webapi/tests.py
+++ b/reviewboard/webapi/tests.py
@@ -423,7 +423,8 @@ class BaseWebAPITestCase(TestCase, EmailTestHelper):
     def _postNewFileAttachmentComment(self, review_request, review_id,
                                       file_attachment, comment_text,
                                       issue_opened=None,
-                                      issue_status=None):
+                                      issue_status=None,
+                                      extra_fields={}):
         """Creates a file attachment comment and returns the payload response."""
         if review_request.local_site:
             local_site_name = review_request.local_site.name
@@ -434,6 +435,7 @@ class BaseWebAPITestCase(TestCase, EmailTestHelper):
             'file_attachment_id': file_attachment.id,
             'text': comment_text,
         }
+        post_data.update(extra_fields)
 
         if issue_opened is not None:
             post_data['issue_opened'] = issue_opened
@@ -6187,6 +6189,74 @@ class FileAttachmentCommentResourceTests(BaseWebAPITestCase):
         self.assertEqual(rsp['stat'], 'fail')
         self.assertEqual(rsp['err']['code'], PERMISSION_DENIED.code)
 
+    def test_post_file_attachment_comments_with_extra_fields(self):
+        """Testing the POST review-requests/<id>/file-attachments/<id>/comments/ API with extra fields"""
+        comment_text = "This is a test comment."
+        extra_fields = {
+            'foo': '123',
+            'bar': '456',
+            'baz': '',
+        }
+
+        rsp = self._postNewReviewRequest()
+        review_request = ReviewRequest.objects.get(
+            pk=rsp['review_request']['id'])
+
+        # Post the file_attachment.
+        rsp = self._postNewFileAttachment(review_request)
+        file_attachment = FileAttachment.objects.get(
+            pk=rsp['file_attachment']['id'])
+        self.assertTrue('links' in rsp['file_attachment'])
+        self.assertTrue('file_attachment_comments' in
+                        rsp['file_attachment']['links'])
+        comments_url = \
+            rsp['file_attachment']['links']['file_attachment_comments']['href']
+
+        # Make these public.
+        review_request.publish(self.user)
+
+        # Post the review.
+        rsp = self._postNewReview(review_request)
+        review = Review.objects.get(pk=rsp['review']['id'])
+
+        rsp = self._postNewFileAttachmentComment(review_request, review.id,
+                                                 file_attachment, comment_text,
+                                                 extra_fields=extra_fields)
+
+        comment = FileAttachmentComment.objects.get(
+            pk=rsp['file_attachment_comment']['id'])
+
+        self.assertTrue('foo' in comment.extra_data)
+        self.assertTrue('bar' in comment.extra_data)
+        self.assertFalse('baz' in comment.extra_data)
+        self.assertEqual(comment.extra_data['foo'], extra_fields['foo'])
+        self.assertEqual(comment.extra_data['bar'], extra_fields['bar'])
+
+        return rsp
+
+    def test_put_file_attachment_comments_with_extra_fields(self):
+        """Testing the PUT review-requests/<id>/file-attachments/<id>/comments/<id>/ API with extra fields"""
+        extra_fields = {
+            'foo': 'abc',
+            'bar': '',
+        }
+
+        rsp = self.test_post_file_attachment_comments_with_extra_fields()
+
+        rsp = self.apiPut(
+            rsp['file_attachment_comment']['links']['self']['href'],
+            extra_fields,
+            expected_mimetype=self.item_mimetype)
+        self.assertEqual(rsp['stat'], 'ok')
+
+        comment = FileAttachmentComment.objects.get(
+            pk=rsp['file_attachment_comment']['id'])
+
+        self.assertTrue('foo' in comment.extra_data)
+        self.assertFalse('bar' in comment.extra_data)
+        self.assertEqual(len(comment.extra_data.keys()), 1)
+        self.assertEqual(comment.extra_data['foo'], extra_fields['foo'])
+
 
 class DraftReviewFileAttachmentCommentResourceTests(BaseWebAPITestCase):
     """Testing the ReviewFileAttachmentCommentResource APIs."""
