diff --git a/ee/spec/controllers/boards/issues_controller_spec.rb b/ee/spec/controllers/boards/issues_controller_spec.rb
index 7f4d9db93c7461112eb2f0a1666b666f72e7703d..312dea93c267c54d4fc20e5d2f48067418a85720 100644
--- a/ee/spec/controllers/boards/issues_controller_spec.rb
+++ b/ee/spec/controllers/boards/issues_controller_spec.rb
@@ -43,10 +43,8 @@
 
           list_issues user: user, board: board, list: list2
 
-          parsed_response = JSON.parse(response.body)
-
           expect(response).to match_response_schema('issues')
-          expect(parsed_response['issues'].length).to eq 2
+          expect(json_response['issues'].length).to eq 2
           expect(development.issues.map(&:relative_position)).not_to include(nil)
         end
       end
@@ -70,10 +68,8 @@
 
         list_issues user: user, board: board
 
-        parsed_response = JSON.parse(response.body)
-
         expect(response).to match_response_schema('issues')
-        expect(parsed_response['issues'].length).to eq 2
+        expect(json_response['issues'].length).to eq 2
       end
     end
 
diff --git a/ee/spec/controllers/boards/lists_controller_spec.rb b/ee/spec/controllers/boards/lists_controller_spec.rb
index 7185782c8a04099c19ee38c42607339ac3f90914..fb64d2474102cce31d39952304fb44ef09562018 100644
--- a/ee/spec/controllers/boards/lists_controller_spec.rb
+++ b/ee/spec/controllers/boards/lists_controller_spec.rb
@@ -24,10 +24,8 @@
 
       read_board_list user: user, board: board
 
-      parsed_response = JSON.parse(response.body)
-
       expect(response).to match_response_schema('lists', dir: 'ee')
-      expect(parsed_response.length).to eq 3
+      expect(json_response.length).to eq 3
     end
 
     context 'with unauthorized user' do
diff --git a/ee/spec/controllers/boards/milestones_controller_spec.rb b/ee/spec/controllers/boards/milestones_controller_spec.rb
index 6f0b1f855a0f50da90c1f89674370099cd34dd54..38d3383f21afbd45ae70a247aa30c37c82fc723e 100644
--- a/ee/spec/controllers/boards/milestones_controller_spec.rb
+++ b/ee/spec/controllers/boards/milestones_controller_spec.rb
@@ -20,11 +20,9 @@
 
           expect(response).to have_gitlab_http_status(200)
 
-          parsed_response = JSON.parse(response.body)
-
           expect(response.content_type).to eq('application/json')
-          expect(parsed_response).to all(match_schema('entities/milestone', dir: 'ee'))
-          expect(parsed_response.size).to eq(1)
+          expect(json_response).to all(match_schema('entities/milestone', dir: 'ee'))
+          expect(json_response.size).to eq(1)
         end
       end
 
diff --git a/ee/spec/controllers/boards/users_controller_spec.rb b/ee/spec/controllers/boards/users_controller_spec.rb
index cd909fdd239b689d04366ee7249ed88f763b3210..14006c67e073fbc81b39efcceb46b9ea2642238f 100644
--- a/ee/spec/controllers/boards/users_controller_spec.rb
+++ b/ee/spec/controllers/boards/users_controller_spec.rb
@@ -22,12 +22,10 @@
                     },
                     format: :json
 
-        parsed_response = JSON.parse(response.body)
-
         expect(response).to have_gitlab_http_status(200)
         expect(response.content_type).to eq 'application/json'
-        expect(parsed_response).to all(match_schema('entities/user'))
-        expect(parsed_response.length).to eq 2
+        expect(json_response).to all(match_schema('entities/user'))
+        expect(json_response.length).to eq 2
       end
     end
 
diff --git a/ee/spec/controllers/groups/boards_controller_spec.rb b/ee/spec/controllers/groups/boards_controller_spec.rb
index 5fc13ea8242e1d3a6d7526c8c5ccb8e85d57e863..c0a7c6b309c4519a0a34380cf63bdfe5d530bd79 100644
--- a/ee/spec/controllers/groups/boards_controller_spec.rb
+++ b/ee/spec/controllers/groups/boards_controller_spec.rb
@@ -23,10 +23,8 @@
 
         list_boards format: :json
 
-        parsed_response = JSON.parse(response.body)
-
         expect(response).to match_response_schema('boards')
-        expect(parsed_response.length).to eq 2
+        expect(json_response.length).to eq 2
       end
 
       context 'with unauthorized user' do
diff --git a/ee/spec/controllers/groups/epic_issues_controller_spec.rb b/ee/spec/controllers/groups/epic_issues_controller_spec.rb
index 89d6ab87f1674e6f54ddccc7208f9ce7aa765ebe..a65ff2ed951faf3ce895678e46671ede566f691b 100644
--- a/ee/spec/controllers/groups/epic_issues_controller_spec.rb
+++ b/ee/spec/controllers/groups/epic_issues_controller_spec.rb
@@ -47,7 +47,7 @@
         end
 
         it 'returns the correct json' do
-          expect(JSON.parse(response.body)).to match_schema('related_issues', dir: 'ee')
+          expect(json_response).to match_schema('related_issues', dir: 'ee')
         end
       end
 
diff --git a/ee/spec/controllers/groups/epics/notes_controller_spec.rb b/ee/spec/controllers/groups/epics/notes_controller_spec.rb
index b402282af27da0a823f83d205396e6167736bd87..f60e69095a58fa6247b32aa1bbc63ef34e4ead9a 100644
--- a/ee/spec/controllers/groups/epics/notes_controller_spec.rb
+++ b/ee/spec/controllers/groups/epics/notes_controller_spec.rb
@@ -5,7 +5,7 @@
   let(:group) { create(:group) }
   let(:epic) { create(:epic, group: group) }
   let(:note) { create(:note, noteable: epic) }
-  let(:parsed_response) { JSON.parse(response.body).with_indifferent_access }
+  let(:parsed_response) { json_response.with_indifferent_access }
 
   before do
     stub_licensed_features(epics: true)
diff --git a/ee/spec/controllers/groups/epics_controller_spec.rb b/ee/spec/controllers/groups/epics_controller_spec.rb
index e7d8524e0373ff5478fba1ea1f7a53ff4ef59ec8..15fbb488bd9679e2bcb307b14ef60f110fbed3b1 100644
--- a/ee/spec/controllers/groups/epics_controller_spec.rb
+++ b/ee/spec/controllers/groups/epics_controller_spec.rb
@@ -375,7 +375,7 @@ def update_epic(epic, params)
         subject
 
         expect(response.content_type).to eq 'application/json'
-        expect(JSON.parse(response.body)).to include('title_text', 'title', 'description', 'description_text')
+        expect(json_response).to include('title_text', 'title', 'description', 'description_text')
       end
 
       context 'with unauthorized user' do
@@ -421,7 +421,7 @@ def update_epic(epic, params)
           it 'returns the correct json' do
             subject
 
-            expect(JSON.parse(response.body)).to eq({ 'web_url' => group_epic_path(group, Epic.last) })
+            expect(json_response).to eq({ 'web_url' => group_epic_path(group, Epic.last) })
           end
 
           it_behaves_like 'disabled when using an external authorization service'
diff --git a/ee/spec/controllers/groups/issues_analytics_controller_spec.rb b/ee/spec/controllers/groups/issues_analytics_controller_spec.rb
index deab548700cda86ad8cbcbe0ee2ba564cd980f4f..fb5457a13e891479a344eb4a9ba92b63ad99f76e 100644
--- a/ee/spec/controllers/groups/issues_analytics_controller_spec.rb
+++ b/ee/spec/controllers/groups/issues_analytics_controller_spec.rb
@@ -58,7 +58,7 @@
 
           get :show, params: { group_id: group.to_param }, format: :json
 
-          expect(JSON.parse(response.body)).to include(expected_result)
+          expect(json_response).to include(expected_result)
         end
 
         context 'when user cannot view issues' do
@@ -74,7 +74,7 @@
 
             get :show, params: { group_id: group.to_param }, format: :json
 
-            expect(JSON.parse(response.body)).to include(expected_result)
+            expect(json_response).to include(expected_result)
           end
         end
       end
diff --git a/ee/spec/controllers/operations_controller_spec.rb b/ee/spec/controllers/operations_controller_spec.rb
index 696ba1881718d75b6fabf4c1ad05f96d0c4be66a..ef01f8b0051211734b0bc239c708c8d5d764894c 100644
--- a/ee/spec/controllers/operations_controller_spec.rb
+++ b/ee/spec/controllers/operations_controller_spec.rb
@@ -6,7 +6,6 @@
   include Rails.application.routes.url_helpers
 
   let(:user) { create(:user) }
-  let(:json_response) { JSON.parse(response.body) }
 
   shared_examples 'unlicensed' do |http_method, action|
     before do
diff --git a/ee/spec/controllers/projects/boards_controller_spec.rb b/ee/spec/controllers/projects/boards_controller_spec.rb
index 0514917e758f0ad30cb84825718fd3196c6f2d12..e47b38fcb6c1812f3364f480aa2caad7ede22256 100644
--- a/ee/spec/controllers/projects/boards_controller_spec.rb
+++ b/ee/spec/controllers/projects/boards_controller_spec.rb
@@ -18,10 +18,8 @@
 
       list_boards
 
-      parsed_response = JSON.parse(response.body)
-
       expect(response).to match_response_schema('boards')
-      expect(parsed_response.length).to eq 2
+      expect(json_response.length).to eq 2
     end
 
     it_behaves_like 'redirects to last visited board'
diff --git a/ee/spec/controllers/projects/managed_licenses_controller_spec.rb b/ee/spec/controllers/projects/managed_licenses_controller_spec.rb
index b0963d0fab948ed49063cc2145be9fb13128011d..07af86e813497a15a573d029ecb429c9f80f8fc9 100644
--- a/ee/spec/controllers/projects/managed_licenses_controller_spec.rb
+++ b/ee/spec/controllers/projects/managed_licenses_controller_spec.rb
@@ -396,7 +396,7 @@
           subject
 
           expect(response).to match_response_schema('software_license_policy', dir: 'ee')
-          expect(JSON.parse(response.body)).to eq(modified_software_license_policy_attributes.with_indifferent_access)
+          expect(json_response).to eq(modified_software_license_policy_attributes.with_indifferent_access)
         end
       end
     end
diff --git a/ee/spec/controllers/projects/merge_requests_controller_spec.rb b/ee/spec/controllers/projects/merge_requests_controller_spec.rb
index b3f1f455543efff3d17c454bbca3d8bd75ac9890..6ac6f5ee7fbe3a1743fd75420020ecf122a05ea6 100644
--- a/ee/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/ee/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -1,10 +1,6 @@
 require 'spec_helper'
 
 shared_examples 'approvals' do
-  def json_response
-    JSON.parse(response.body)
-  end
-
   let!(:approver) { create(:user) }
   let!(:approval_rule) { create(:approval_project_rule, project: project, users: [approver, user], approvals_required: 2) }
 
diff --git a/ee/spec/controllers/projects/service_desk_controller_spec.rb b/ee/spec/controllers/projects/service_desk_controller_spec.rb
index fe7e2afc1303355380353cc6254592794a3265e1..8fb903a1a1d1be8751627298c5186beb32d55c44 100644
--- a/ee/spec/controllers/projects/service_desk_controller_spec.rb
+++ b/ee/spec/controllers/projects/service_desk_controller_spec.rb
@@ -18,10 +18,8 @@
     it 'returns service_desk JSON data' do
       get :show, params: { namespace_id: project.namespace.to_param, project_id: project }, format: :json
 
-      body = JSON.parse(response.body)
-
-      expect(body["service_desk_address"]).to match(/\A[^@]+@[^@]+\z/)
-      expect(body["service_desk_enabled"]).to be_truthy
+      expect(json_response["service_desk_address"]).to match(/\A[^@]+@[^@]+\z/)
+      expect(json_response["service_desk_enabled"]).to be_truthy
       expect(response.status).to eq(200)
     end
 
@@ -45,10 +43,8 @@
 
       put :update, params: { namespace_id: project.namespace.to_param, project_id: project, service_desk_enabled: true }, format: :json
 
-      body = JSON.parse(response.body)
-
-      expect(body["service_desk_address"]).to be_present
-      expect(body["service_desk_enabled"]).to be_truthy
+      expect(json_response["service_desk_address"]).to be_present
+      expect(json_response["service_desk_enabled"]).to be_truthy
       expect(response.status).to eq(200)
     end
 
diff --git a/ee/spec/requests/api/epic_links_spec.rb b/ee/spec/requests/api/epic_links_spec.rb
index 552cec2d3afb76d238c36aaedd3d0900ebddf50e..1bd804c40e7f21a5aed357b9ccf8c0e8a57ca05a 100644
--- a/ee/spec/requests/api/epic_links_spec.rb
+++ b/ee/spec/requests/api/epic_links_spec.rb
@@ -53,7 +53,7 @@
       it 'returns 200 status' do
         subject
 
-        epics = JSON.parse(response.body)
+        epics = json_response
 
         expect(response).to have_gitlab_http_status(200)
         expect(response).to match_response_schema('public_api/v4/epics', dir: 'ee')
diff --git a/ee/spec/requests/api/epics_spec.rb b/ee/spec/requests/api/epics_spec.rb
index f1de9f3d5bb1ec05461a45f6b042d14962a07998..fda2d658894d4549a109c238293c4c8d87727673 100644
--- a/ee/spec/requests/api/epics_spec.rb
+++ b/ee/spec/requests/api/epics_spec.rb
@@ -44,7 +44,7 @@
       it 'returns epic with extra date fields' do
         get api(url, user), params: params
 
-        expect(Array.wrap(JSON.parse(response.body))).to all(exclude(*extra_date_fields))
+        expect(Array.wrap(json_response)).to all(exclude(*extra_date_fields))
       end
     end
 
@@ -56,7 +56,7 @@
       it 'returns epic with extra date fields' do
         get api(url, user), params: params
 
-        expect(Array.wrap(JSON.parse(response.body))).to all(include(*extra_date_fields))
+        expect(Array.wrap(json_response)).to all(include(*extra_date_fields))
       end
     end
   end
diff --git a/ee/spec/requests/api/project_approvals_spec.rb b/ee/spec/requests/api/project_approvals_spec.rb
index 405cf11e49e7e313296d463b02eb6c5118204b34..584f6faff495a1b2873c079f9344f6f46d593d23 100644
--- a/ee/spec/requests/api/project_approvals_spec.rb
+++ b/ee/spec/requests/api/project_approvals_spec.rb
@@ -77,7 +77,7 @@
 
           post api(url, current_user), params: settings
 
-          expect(JSON.parse(response.body).symbolize_keys).to include(settings)
+          expect(json_response.symbolize_keys).to include(settings)
         end
 
         it 'only shows approver groups that are visible to the current user' do
diff --git a/spec/controllers/admin/application_settings_controller_spec.rb b/spec/controllers/admin/application_settings_controller_spec.rb
index 5ad5f9cdeea8b1e0ce0e0ca6fbf9596f9d60081f..4eb0545eb6c4e929978dcc7daeb3af20f4d9ad72 100644
--- a/spec/controllers/admin/application_settings_controller_spec.rb
+++ b/spec/controllers/admin/application_settings_controller_spec.rb
@@ -41,7 +41,7 @@
     it 'returns JSON data' do
       get :usage_data, format: :json
 
-      body = JSON.parse(response.body)
+      body = json_response
       expect(body["version"]).to eq(Gitlab::VERSION)
       expect(body).to include('counts')
       expect(response.status).to eq(200)
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
index 447a12b2facf6963d5a356469b22bcef9a685ace..84bbbac39b0bfe660b4f2d9a9d018aca4e5144cd 100644
--- a/spec/controllers/application_controller_spec.rb
+++ b/spec/controllers/application_controller_spec.rb
@@ -63,8 +63,6 @@
       sign_in user
     end
 
-    let(:json_response) { JSON.parse(response.body) }
-
     controller(described_class) do
       def index
         render json: Gon.all_variables
diff --git a/spec/controllers/boards/issues_controller_spec.rb b/spec/controllers/boards/issues_controller_spec.rb
index 6cad060d88851c3f308fb783d3aedd903355d91c..246d6f9e0f992a8869906580d14dc7d28bf2192b 100644
--- a/spec/controllers/boards/issues_controller_spec.rb
+++ b/spec/controllers/boards/issues_controller_spec.rb
@@ -52,10 +52,8 @@
 
           list_issues user: user, board: board, list: list2
 
-          parsed_response = JSON.parse(response.body)
-
           expect(response).to match_response_schema('entities/issue_boards')
-          expect(parsed_response['issues'].length).to eq 2
+          expect(json_response['issues'].length).to eq 2
           expect(development.issues.map(&:relative_position)).not_to include(nil)
         end
 
@@ -123,10 +121,8 @@
 
         list_issues user: user, board: board
 
-        parsed_response = JSON.parse(response.body)
-
         expect(response).to match_response_schema('entities/issue_boards')
-        expect(parsed_response['issues'].length).to eq 2
+        expect(json_response['issues'].length).to eq 2
       end
     end
 
diff --git a/spec/controllers/boards/lists_controller_spec.rb b/spec/controllers/boards/lists_controller_spec.rb
index e1f75fa339566057cbff51549a9773d1514bd588..418ca6f32100eb113a7f2e200141ec13f69862eb 100644
--- a/spec/controllers/boards/lists_controller_spec.rb
+++ b/spec/controllers/boards/lists_controller_spec.rb
@@ -26,10 +26,8 @@
 
       read_board_list user: user, board: board
 
-      parsed_response = JSON.parse(response.body)
-
       expect(response).to match_response_schema('lists')
-      expect(parsed_response.length).to eq 3
+      expect(json_response.length).to eq 3
     end
 
     context 'with unauthorized user' do
diff --git a/spec/controllers/groups/boards_controller_spec.rb b/spec/controllers/groups/boards_controller_spec.rb
index 5e0f64ccca407a76b4f06e31f8e37bb31875f2c6..e4232c2c1abca2e58848eeab5d2a8b0f4cb5c83d 100644
--- a/spec/controllers/groups/boards_controller_spec.rb
+++ b/spec/controllers/groups/boards_controller_spec.rb
@@ -63,10 +63,8 @@
 
         list_boards format: :json
 
-        parsed_response = JSON.parse(response.body)
-
         expect(response).to match_response_schema('boards')
-        expect(parsed_response.length).to eq 1
+        expect(json_response.length).to eq 1
       end
 
       context 'with unauthorized user' do
diff --git a/spec/controllers/groups/milestones_controller_spec.rb b/spec/controllers/groups/milestones_controller_spec.rb
index 19b18091aef0f40283d2cdb25688fa4c6b4cfcc7..bf164aeed38def37c13f9de4d8c129a02b48ff81 100644
--- a/spec/controllers/groups/milestones_controller_spec.rb
+++ b/spec/controllers/groups/milestones_controller_spec.rb
@@ -73,7 +73,7 @@
       it 'lists legacy group milestones and group milestones' do
         get :index, params: { group_id: group.to_param }, format: :json
 
-        milestones = JSON.parse(response.body)
+        milestones = json_response
 
         expect(milestones.count).to eq(2)
         expect(milestones.first["title"]).to eq("group milestone")
diff --git a/spec/controllers/health_check_controller_spec.rb b/spec/controllers/health_check_controller_spec.rb
index 19d739fcf4fcd75d9121af5ac9571e0f48409e7f..92f005faf4a31d6b352f33bd10a6010d432e7ee8 100644
--- a/spec/controllers/health_check_controller_spec.rb
+++ b/spec/controllers/health_check_controller_spec.rb
@@ -5,7 +5,6 @@
 describe HealthCheckController do
   include StubENV
 
-  let(:json_response) { JSON.parse(response.body) }
   let(:xml_response) { Hash.from_xml(response.body)['hash'] }
   let(:token) { Gitlab::CurrentSettings.health_check_access_token }
   let(:whitelisted_ip) { '127.0.0.1' }
diff --git a/spec/controllers/health_controller_spec.rb b/spec/controllers/health_controller_spec.rb
index fc62a8310aab0cfb21462d472379b2fee3691aa9..e82dcfcdb64383e596573859c93b445628a1f069 100644
--- a/spec/controllers/health_controller_spec.rb
+++ b/spec/controllers/health_controller_spec.rb
@@ -5,7 +5,6 @@
 describe HealthController do
   include StubENV
 
-  let(:json_response) { JSON.parse(response.body) }
   let(:token) { Gitlab::CurrentSettings.health_check_access_token }
   let(:whitelisted_ip) { '127.0.0.1' }
   let(:not_whitelisted_ip) { '127.0.0.2' }
diff --git a/spec/controllers/metrics_controller_spec.rb b/spec/controllers/metrics_controller_spec.rb
index ee454a7818c859a38f84aa2fd5f72362d1826ed5..84027119491d68a11065b1865cea81b348dfdf12 100644
--- a/spec/controllers/metrics_controller_spec.rb
+++ b/spec/controllers/metrics_controller_spec.rb
@@ -5,7 +5,6 @@
 describe MetricsController do
   include StubENV
 
-  let(:json_response) { JSON.parse(response.body) }
   let(:metrics_multiproc_dir) { Dir.mktmpdir }
   let(:whitelisted_ip) { '127.0.0.1' }
   let(:whitelisted_ip_range) { '10.0.0.0/24' }
diff --git a/spec/controllers/projects/blob_controller_spec.rb b/spec/controllers/projects/blob_controller_spec.rb
index 44500d3cde34c92c3a5cc0275bee94ae8b0c9bda..45aebd1554c4b9e07e96df37e28fdaedb1b63072 100644
--- a/spec/controllers/projects/blob_controller_spec.rb
+++ b/spec/controllers/projects/blob_controller_spec.rb
@@ -160,7 +160,7 @@ def do_get(opts = {})
         it 'renders diff context lines Gitlab::Diff::Line array' do
           do_get(since: 1, to: 2, offset: 0, from_merge_request: true)
 
-          lines = JSON.parse(response.body)
+          lines = json_response
 
           expect(lines.size).to eq(diff_lines.size)
           lines.each do |line|
@@ -173,7 +173,7 @@ def do_get(opts = {})
         it 'handles full being true' do
           do_get(full: true, from_merge_request: true)
 
-          lines = JSON.parse(response.body)
+          lines = json_response
 
           expect(lines.size).to eq(diff_lines.size)
         end
diff --git a/spec/controllers/projects/boards_controller_spec.rb b/spec/controllers/projects/boards_controller_spec.rb
index c07afc57aeacc48a1e9d03a7421e1fc75cba730f..543479d8dd51721412b8a470d96241a79d2105fa 100644
--- a/spec/controllers/projects/boards_controller_spec.rb
+++ b/spec/controllers/projects/boards_controller_spec.rb
@@ -69,10 +69,8 @@
 
         list_boards format: :json
 
-        parsed_response = JSON.parse(response.body)
-
         expect(response).to match_response_schema('boards')
-        expect(parsed_response.length).to eq 2
+        expect(json_response.length).to eq 2
       end
 
       context 'with unauthorized user' do
diff --git a/spec/controllers/projects/branches_controller_spec.rb b/spec/controllers/projects/branches_controller_spec.rb
index b30966e70a7d99bf4b67b83ca0c38f473984edf7..f5bcea4a097d760d1384fc1339108fa21a43607d 100644
--- a/spec/controllers/projects/branches_controller_spec.rb
+++ b/spec/controllers/projects/branches_controller_spec.rb
@@ -495,10 +495,8 @@ def destroy_all_merged
               search: 'master'
             }
 
-        parsed_response = JSON.parse(response.body)
-
-        expect(parsed_response.length).to eq 1
-        expect(parsed_response.first).to eq 'master'
+        expect(json_response.length).to eq 1
+        expect(json_response.first).to eq 'master'
       end
     end
 
@@ -591,8 +589,7 @@ def destroy_all_merged
     end
 
     it 'returns the commit counts behind and ahead of default branch' do
-      parsed_response = JSON.parse(response.body)
-      expect(parsed_response).to eq(
+      expect(json_response).to eq(
         "fix" => { "behind" => 29, "ahead" => 2 },
         "branch-merged" => { "behind" => 1, "ahead" => 0 },
         "add-pdf-file" => { "behind" => 0, "ahead" => 3 }
diff --git a/spec/controllers/projects/commit_controller_spec.rb b/spec/controllers/projects/commit_controller_spec.rb
index b5c6382a26d5244070982b3cef0301c51eb52b38..58a1d96d010c1ae688252dfb1e809f5db3cbd764 100644
--- a/spec/controllers/projects/commit_controller_spec.rb
+++ b/spec/controllers/projects/commit_controller_spec.rb
@@ -378,8 +378,8 @@ def get_pipelines(extra_params = {})
             get_pipelines(id: commit.id, format: :json)
 
             expect(response).to be_ok
-            expect(JSON.parse(response.body)['pipelines']).not_to be_empty
-            expect(JSON.parse(response.body)['count']['all']).to eq 1
+            expect(json_response['pipelines']).not_to be_empty
+            expect(json_response['count']['all']).to eq 1
             expect(response).to include_pagination_headers
           end
         end
diff --git a/spec/controllers/projects/compare_controller_spec.rb b/spec/controllers/projects/compare_controller_spec.rb
index 92380a2bf09f503d5498f8fdb9e21ad1964c9786..48a92a772dce3e449ff355e80bd7f6c5559a08c0 100644
--- a/spec/controllers/projects/compare_controller_spec.rb
+++ b/spec/controllers/projects/compare_controller_spec.rb
@@ -302,8 +302,7 @@ def diff_for_path(extra_params = {})
           signatures_request
 
           expect(response).to have_gitlab_http_status(200)
-          parsed_body = JSON.parse(response.body)
-          signatures = parsed_body['signatures']
+          signatures = json_response['signatures']
 
           expect(signatures.size).to eq(1)
           expect(signatures.first['commit_sha']).to eq(signature_commit.sha)
@@ -332,8 +331,7 @@ def diff_for_path(extra_params = {})
         signatures_request
 
         expect(response).to have_gitlab_http_status(200)
-        parsed_body = JSON.parse(response.body)
-        expect(parsed_body['signatures']).to be_empty
+        expect(json_response['signatures']).to be_empty
       end
     end
 
@@ -345,8 +343,7 @@ def diff_for_path(extra_params = {})
         signatures_request
 
         expect(response).to have_gitlab_http_status(200)
-        parsed_body = JSON.parse(response.body)
-        expect(parsed_body['signatures']).to be_empty
+        expect(json_response['signatures']).to be_empty
       end
     end
   end
diff --git a/spec/controllers/projects/deploy_keys_controller_spec.rb b/spec/controllers/projects/deploy_keys_controller_spec.rb
index fcd14f13863483e39c0350340baef509a465ea49..ccad76eadddc156689b7acc2364eb5dad058ff91 100644
--- a/spec/controllers/projects/deploy_keys_controller_spec.rb
+++ b/spec/controllers/projects/deploy_keys_controller_spec.rb
@@ -52,12 +52,10 @@
       it 'returns json in a correct format' do
         get :index, params: params.merge(format: :json)
 
-        json = JSON.parse(response.body)
-
-        expect(json.keys).to match_array(%w(enabled_keys available_project_keys public_keys))
-        expect(json['enabled_keys'].count).to eq(1)
-        expect(json['available_project_keys'].count).to eq(1)
-        expect(json['public_keys'].count).to eq(1)
+        expect(json_response.keys).to match_array(%w(enabled_keys available_project_keys public_keys))
+        expect(json_response['enabled_keys'].count).to eq(1)
+        expect(json_response['available_project_keys'].count).to eq(1)
+        expect(json_response['public_keys'].count).to eq(1)
       end
     end
   end
diff --git a/spec/controllers/projects/discussions_controller_spec.rb b/spec/controllers/projects/discussions_controller_spec.rb
index 4c29162cd0f7d084ded4ee1d6b04475fcddf0c0e..e30b28a4bd57a091c2feeeb249efa2bc82bd8a15 100644
--- a/spec/controllers/projects/discussions_controller_spec.rb
+++ b/spec/controllers/projects/discussions_controller_spec.rb
@@ -112,7 +112,7 @@
         it "returns the name of the resolving user" do
           post :resolve, params: request_params
 
-          expect(JSON.parse(response.body)['resolved_by']['name']).to eq(user.name)
+          expect(json_response['resolved_by']['name']).to eq(user.name)
         end
 
         it "returns status 200" do
@@ -135,7 +135,7 @@
           it "returns truncated diff lines" do
             post :resolve, params: request_params
 
-            expect(JSON.parse(response.body)['truncated_diff_lines']).to be_present
+            expect(json_response['truncated_diff_lines']).to be_present
           end
         end
       end
diff --git a/spec/controllers/projects/find_file_controller_spec.rb b/spec/controllers/projects/find_file_controller_spec.rb
index 538dbb5ad0bc98603bcd21d2ba375e54ccc574b5..a493985f8a06a80f541b90e734a7fcc1d58a5d8d 100644
--- a/spec/controllers/projects/find_file_controller_spec.rb
+++ b/spec/controllers/projects/find_file_controller_spec.rb
@@ -53,10 +53,9 @@ def go(format: 'json')
       it 'returns an array of file path list' do
         go
 
-        json = JSON.parse(response.body)
         is_expected.to respond_with(:success)
-        expect(json).not_to eq(nil)
-        expect(json.length).to be >= 0
+        expect(json_response).not_to eq(nil)
+        expect(json_response.length).to be >= 0
       end
     end
 
diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb
index bc5e0b4671edbe1f58f78109dd2adf5c45fac71c..32d14dce936caa7a3f1785733147ad904e11bf20 100644
--- a/spec/controllers/projects/issues_controller_spec.rb
+++ b/spec/controllers/projects/issues_controller_spec.rb
@@ -444,7 +444,7 @@ def reorder_issue(issue, move_after_id: nil, move_before_id: nil, group_full_pat
         it 'renders json with recaptcha_html' do
           subject
 
-          expect(JSON.parse(response.body)).to have_key('recaptcha_html')
+          expect(json_response).to have_key('recaptcha_html')
         end
       end
     end
@@ -484,10 +484,8 @@ def go(id:)
       it 'returns last edited time' do
         go(id: issue.iid)
 
-        data = JSON.parse(response.body)
-
-        expect(data).to include('updated_at')
-        expect(data['updated_at']).to eq(issue.last_edited_at.to_time.iso8601)
+        expect(json_response).to include('updated_at')
+        expect(json_response['updated_at']).to eq(issue.last_edited_at.to_time.iso8601)
       end
     end
 
@@ -520,10 +518,8 @@ def go(id:)
       it 'returns the necessary data' do
         go(id: issue.iid)
 
-        data = JSON.parse(response.body)
-
-        expect(data).to include('title_text', 'description', 'description_text')
-        expect(data).to include('task_status', 'lock_version')
+        expect(json_response).to include('title_text', 'description', 'description_text')
+        expect(json_response).to include('task_status', 'lock_version')
       end
     end
   end
@@ -692,9 +688,7 @@ def go(id:)
 
           update_issue(issue_params: { assignee_ids: [assignee.id] })
 
-          body = JSON.parse(response.body)
-
-          expect(body['assignees'].first.keys)
+          expect(json_response['assignees'].first.keys)
             .to match_array(%w(id name username avatar_url state web_url))
         end
       end
@@ -1314,7 +1308,7 @@ def import_csv
         it 'filters notes that the user should not see' do
           get :discussions, params: { namespace_id: project.namespace, project_id: project, id: issue.iid }
 
-          expect(JSON.parse(response.body).count).to eq(1)
+          expect(json_response.count).to eq(1)
         end
 
         it 'does not result in N+1 queries' do
diff --git a/spec/controllers/projects/merge_requests/diffs_controller_spec.rb b/spec/controllers/projects/merge_requests/diffs_controller_spec.rb
index 13a28b738ca156d14137ea51300932f178dc77a6..d940d226176f85dae15bf66d2f4ebf2edb6b7f3a 100644
--- a/spec/controllers/projects/merge_requests/diffs_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests/diffs_controller_spec.rb
@@ -112,7 +112,7 @@ def diff_for_path(extra_params = {})
           it 'only renders the diffs for the path given' do
             diff_for_path(old_path: existing_path, new_path: existing_path)
 
-            paths = JSON.parse(response.body)["diff_files"].map { |file| file['new_path'] }
+            paths = json_response["diff_files"].map { |file| file['new_path'] }
 
             expect(paths).to include(existing_path)
           end
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index cc6adc0a6c6598ba685ad96b557202fc0dacc2f6..f11880122b117cad0fcee16dc8ae6ba2f4153bcd 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -242,9 +242,7 @@ def update_merge_request(mr_params, additional_params = {})
 
         update_merge_request({ assignee_ids: [assignee.id] }, format: :json)
 
-        body = JSON.parse(response.body)
-
-        expect(body['assignees']).to all(include(*%w(name username avatar_url id state web_url)))
+        expect(json_response['assignees']).to all(include(*%w(name username avatar_url id state web_url)))
       end
     end
 
diff --git a/spec/controllers/projects/notes_controller_spec.rb b/spec/controllers/projects/notes_controller_spec.rb
index 1db1963476c74b34e0367b65fea41609fb66a815..98aea9056dcd0356b18a1f86c3ee472e8ff372a3 100644
--- a/spec/controllers/projects/notes_controller_spec.rb
+++ b/spec/controllers/projects/notes_controller_spec.rb
@@ -29,7 +29,7 @@
       }
     end
 
-    let(:parsed_response) { JSON.parse(response.body).with_indifferent_access }
+    let(:parsed_response) { json_response.with_indifferent_access }
     let(:note_json) { parsed_response[:notes].first }
 
     before do
@@ -614,7 +614,7 @@ def post_create(extra_params = {})
           it "returns the name of the resolving user" do
             post :resolve, params: request_params.merge(html: true)
 
-            expect(JSON.parse(response.body)["resolved_by"]).to eq(user.name)
+            expect(json_response["resolved_by"]).to eq(user.name)
           end
 
           it "returns status 200" do
diff --git a/spec/controllers/projects/templates_controller_spec.rb b/spec/controllers/projects/templates_controller_spec.rb
index 9e7d34b10c007da115c7bf83fe18e0e9a8144d3f..d5ef2b0e114868ac3bdffaea1e3fe44c44b712aa 100644
--- a/spec/controllers/projects/templates_controller_spec.rb
+++ b/spec/controllers/projects/templates_controller_spec.rb
@@ -7,7 +7,6 @@
   let(:user) { create(:user) }
   let(:file_path_1) { '.gitlab/issue_templates/issue_template.md' }
   let(:file_path_2) { '.gitlab/merge_request_templates/merge_request_template.md' }
-  let(:body) { JSON.parse(response.body) }
   let!(:file_1) { project.repository.create_file(user, file_path_1, 'issue content', message: 'message', branch_name: 'master') }
   let!(:file_2) { project.repository.create_file(user, file_path_2, 'merge request content', message: 'message', branch_name: 'master') }
 
@@ -17,8 +16,8 @@
         get(:show, params: { namespace_id: project.namespace, template_type: 'issue', key: 'issue_template', project_id: project }, format: :json)
 
         expect(response.status).to eq(200)
-        expect(body['name']).to eq('issue_template')
-        expect(body['content']).to eq('issue content')
+        expect(json_response['name']).to eq('issue_template')
+        expect(json_response['content']).to eq('issue content')
       end
     end
 
@@ -27,8 +26,8 @@
         get(:show, params: { namespace_id: project.namespace, template_type: 'merge_request', key: 'merge_request_template', project_id: project }, format: :json)
 
         expect(response.status).to eq(200)
-        expect(body['name']).to eq('merge_request_template')
-        expect(body['content']).to eq('merge request content')
+        expect(json_response['name']).to eq('merge_request_template')
+        expect(json_response['content']).to eq('merge request content')
       end
     end
 
diff --git a/spec/controllers/projects/wikis_controller_spec.rb b/spec/controllers/projects/wikis_controller_spec.rb
index f2e0b5e5c1de3606408157484c683b0223215d78..a7e5a79b51dd7421973bd2c32119a0dcfe6f0953 100644
--- a/spec/controllers/projects/wikis_controller_spec.rb
+++ b/spec/controllers/projects/wikis_controller_spec.rb
@@ -103,7 +103,7 @@
     it 'renders json in a correct format' do
       post :preview_markdown, params: { namespace_id: project.namespace, project_id: project, id: 'page/path', text: '*Markdown* text' }
 
-      expect(JSON.parse(response.body).keys).to match_array(%w(body references))
+      expect(json_response.keys).to match_array(%w(body references))
     end
   end
 
diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb
index 4e1cac67d23634974c2ee4edb2dfc92acf1d3544..083a1c1383af550848a8ca4ab25bd5d2f41d67ec 100644
--- a/spec/controllers/projects_controller_spec.rb
+++ b/spec/controllers/projects_controller_spec.rb
@@ -740,20 +740,18 @@ def update_project(**parameters)
     it 'gets a list of branches and tags' do
       get :refs, params: { namespace_id: project.namespace, id: project, sort: 'updated_desc' }
 
-      parsed_body = JSON.parse(response.body)
-      expect(parsed_body['Branches']).to include('master')
-      expect(parsed_body['Tags'].first).to eq('v1.1.0')
-      expect(parsed_body['Tags'].last).to eq('v1.0.0')
-      expect(parsed_body['Commits']).to be_nil
+      expect(json_response['Branches']).to include('master')
+      expect(json_response['Tags'].first).to eq('v1.1.0')
+      expect(json_response['Tags'].last).to eq('v1.0.0')
+      expect(json_response['Commits']).to be_nil
     end
 
     it "gets a list of branches, tags and commits" do
       get :refs, params: { namespace_id: project.namespace, id: project, ref: "123456" }
 
-      parsed_body = JSON.parse(response.body)
-      expect(parsed_body["Branches"]).to include("master")
-      expect(parsed_body["Tags"]).to include("v1.0.0")
-      expect(parsed_body["Commits"]).to include("123456")
+      expect(json_response["Branches"]).to include("master")
+      expect(json_response["Tags"]).to include("v1.0.0")
+      expect(json_response["Commits"]).to include("123456")
     end
 
     context "when preferred language is Japanese" do
@@ -765,10 +763,9 @@ def update_project(**parameters)
       it "gets a list of branches, tags and commits" do
         get :refs, params: { namespace_id: project.namespace, id: project, ref: "123456" }
 
-        parsed_body = JSON.parse(response.body)
-        expect(parsed_body["Branches"]).to include("master")
-        expect(parsed_body["Tags"]).to include("v1.0.0")
-        expect(parsed_body["Commits"]).to include("123456")
+        expect(json_response["Branches"]).to include("master")
+        expect(json_response["Tags"]).to include("v1.0.0")
+        expect(json_response["Commits"]).to include("123456")
       end
     end
 
@@ -797,7 +794,7 @@ def update_project(**parameters)
     it 'renders json in a correct format' do
       post :preview_markdown, params: { namespace_id: public_project.namespace, id: public_project, text: '*Markdown* text' }
 
-      expect(JSON.parse(response.body).keys).to match_array(%w(body references))
+      expect(json_response.keys).to match_array(%w(body references))
     end
 
     context 'when not authorized' do
@@ -821,8 +818,6 @@ def update_project(**parameters)
                                   text: issue.to_reference
                                 }
 
-        json_response = JSON.parse(response.body)
-
         expect(json_response['body']).to match(/\##{issue.iid} \(closed\)/)
       end
 
@@ -833,8 +828,6 @@ def update_project(**parameters)
                                   text: merge_request.to_reference
                                 }
 
-        json_response = JSON.parse(response.body)
-
         expect(json_response['body']).to match(/\!#{merge_request.iid} \(closed\)/)
       end
     end
diff --git a/spec/controllers/snippets/notes_controller_spec.rb b/spec/controllers/snippets/notes_controller_spec.rb
index 586d59c2d09cf364738081f63ad2729897fbea2d..652533ac49fd883595b8d16679c57a0759ff725b 100644
--- a/spec/controllers/snippets/notes_controller_spec.rb
+++ b/spec/controllers/snippets/notes_controller_spec.rb
@@ -26,7 +26,7 @@
       end
 
       it "returns not empty array of notes" do
-        expect(JSON.parse(response.body)["notes"].empty?).to be_falsey
+        expect(json_response["notes"].empty?).to be_falsey
       end
     end
 
@@ -97,7 +97,7 @@
         it "returns 1 note" do
           get :index, params: { snippet_id: private_snippet }
 
-          expect(JSON.parse(response.body)['notes'].count).to eq(1)
+          expect(json_response['notes'].count).to eq(1)
         end
       end
     end
@@ -114,7 +114,7 @@
       it "does not return any note" do
         get :index, params: { snippet_id: public_snippet }
 
-        expect(JSON.parse(response.body)['notes'].count).to eq(0)
+        expect(json_response['notes'].count).to eq(0)
       end
     end
   end
diff --git a/spec/controllers/snippets_controller_spec.rb b/spec/controllers/snippets_controller_spec.rb
index 3aba02bf3ff58905168d826520a9fb0c5e497472..b0092bc89945e5da1023d334f97540a29eb5f4a6 100644
--- a/spec/controllers/snippets_controller_spec.rb
+++ b/spec/controllers/snippets_controller_spec.rb
@@ -622,7 +622,7 @@ def mark_as_spam
 
       post :preview_markdown, params: { id: snippet, text: '*Markdown* text' }
 
-      expect(JSON.parse(response.body).keys).to match_array(%w(body references))
+      expect(json_response.keys).to match_array(%w(body references))
     end
   end
 end
diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb
index c3d6ea9cbcde973de2365fd16d7cba4e8f3ba805..8b8d4c57000e678fdcceb977947bbeab3b5dc476 100644
--- a/spec/controllers/users_controller_spec.rb
+++ b/spec/controllers/users_controller_spec.rb
@@ -291,7 +291,7 @@ def create_note_event
       it 'response with snippets json data' do
         get :snippets, params: { username: user.username }, format: :json
         expect(response).to have_gitlab_http_status(200)
-        expect(JSON.parse(response.body)).to have_key('html')
+        expect(json_response).to have_key('html')
       end
     end
 
diff --git a/spec/requests/api/search_spec.rb b/spec/requests/api/search_spec.rb
index 3e0b478abb3c190c62fe1536feb872821251dcfd..8abdcaa2e0e96adcbc3e940ac02761b5e3e56ea9 100644
--- a/spec/requests/api/search_spec.rb
+++ b/spec/requests/api/search_spec.rb
@@ -89,7 +89,7 @@
           it 'returns empty array' do
             get api('/search', user), params: { scope: 'milestones', search: 'awesome' }
 
-            milestones = JSON.parse(response.body)
+            milestones = json_response
 
             expect(milestones).to be_empty
           end
@@ -356,7 +356,7 @@
           it 'returns empty array' do
             get api("/projects/#{project.id}/search", user), params: { scope: 'milestones', search: 'awesome' }
 
-            milestones = JSON.parse(response.body)
+            milestones = json_response
 
             expect(milestones).to be_empty
           end
diff --git a/spec/requests/lfs_http_spec.rb b/spec/requests/lfs_http_spec.rb
index 1781759c54bb09b4b34b8ca4724dac829f0ed200..dc25e4d808ee1c8909208352d7eb86147456001b 100644
--- a/spec/requests/lfs_http_spec.rb
+++ b/spec/requests/lfs_http_spec.rb
@@ -1439,8 +1439,4 @@ def post_lfs_json(url, body = nil, headers = nil)
 
     post(url, params: params, headers: headers)
   end
-
-  def json_response
-    @json_response ||= JSON.parse(response.body)
-  end
 end
diff --git a/spec/requests/lfs_locks_api_spec.rb b/spec/requests/lfs_locks_api_spec.rb
index 5b7b3d2fdd6d428d1bb95a0185e1118ef207e356..11436e5cd0ce3a85985221af68e5651e6f276585 100644
--- a/spec/requests/lfs_locks_api_spec.rb
+++ b/spec/requests/lfs_locks_api_spec.rb
@@ -163,8 +163,4 @@ def post_lfs_json(url, body = nil, headers = nil)
   def do_get(url, params = nil, headers = nil)
     get(url, params: (params || {}), headers: (headers || {}).merge('Content-Type' => LfsRequest::CONTENT_TYPE))
   end
-
-  def json_response
-    @json_response ||= JSON.parse(response.body)
-  end
 end
diff --git a/spec/support/json_response.rb b/spec/support/json_response.rb
index 210b0e6d867d5a955edb1a4868a7bf16bb4377b3..43d8ab73dde69a94ac006e6aa01eb9adc33050f3 100644
--- a/spec/support/json_response.rb
+++ b/spec/support/json_response.rb
@@ -1,5 +1,5 @@
 RSpec.configure do |config|
-  config.include_context 'JSON response'
+  config.include_context 'JSON response', type: :controller
   config.include_context 'JSON response', type: :request
   config.include_context 'JSON response', :api
 end
diff --git a/spec/support/shared_examples/controllers/issuable_notes_filter_shared_examples.rb b/spec/support/shared_examples/controllers/issuable_notes_filter_shared_examples.rb
index 0acc9e2a836f9d83b78457239979f64c97423a54..f4b02dc5350f6f63b1eaab9153fa0dd8e7a8f994 100644
--- a/spec/support/shared_examples/controllers/issuable_notes_filter_shared_examples.rb
+++ b/spec/support/shared_examples/controllers/issuable_notes_filter_shared_examples.rb
@@ -46,7 +46,7 @@
     user.set_notes_filter(UserPreference::NOTES_FILTERS[:only_comments], issuable)
 
     get :discussions, params: params
-    discussions = JSON.parse(response.body)
+    discussions = json_response
 
     expect(discussions.count).to eq(1)
     expect(discussions.first["notes"].first["system"]).to be(false)
@@ -56,7 +56,7 @@
     user.set_notes_filter(UserPreference::NOTES_FILTERS[:only_activity], issuable)
 
     get :discussions, params: params
-    discussions = JSON.parse(response.body)
+    discussions = json_response
 
     expect(discussions.count).to eq(1)
     expect(discussions.first["notes"].first["system"]).to be(true)
diff --git a/spec/support/shared_examples/update_invalid_issuable.rb b/spec/support/shared_examples/update_invalid_issuable.rb
index 64568de424e788fc17382f22fb4d5c08be47041f..4cb6d001b9b17e2160ab0064f83ac0ff3d005a6c 100644
--- a/spec/support/shared_examples/update_invalid_issuable.rb
+++ b/spec/support/shared_examples/update_invalid_issuable.rb
@@ -38,7 +38,7 @@
       put :update, params: params
 
       expect(response.status).to eq(409)
-      expect(JSON.parse(response.body)).to have_key('errors')
+      expect(json_response).to have_key('errors')
     end
   end