diff --git a/core/modules/rest/src/Plugin/rest/resource/EntityResource.php b/core/modules/rest/src/Plugin/rest/resource/EntityResource.php
index a9e0ff0..94ec888 100644
--- a/core/modules/rest/src/Plugin/rest/resource/EntityResource.php
+++ b/core/modules/rest/src/Plugin/rest/resource/EntityResource.php
@@ -297,7 +297,7 @@ public function patch(EntityInterface $original_entity, EntityInterface $entity
     }
 
     // Validate the received data before saving.
-    $this->validate($original_entity);
+    $this->validateWithFilteredFields($original_entity, $entity->_restSubmittedFields);
     try {
       $original_entity->save();
       $this->logger->notice('Updated entity %type with ID %id.', ['%type' => $original_entity->getEntityTypeId(), '%id' => $original_entity->id()]);
diff --git a/core/modules/rest/src/Plugin/rest/resource/EntityResourceValidationTrait.php b/core/modules/rest/src/Plugin/rest/resource/EntityResourceValidationTrait.php
index 09b4b64..97ba3a6 100644
--- a/core/modules/rest/src/Plugin/rest/resource/EntityResourceValidationTrait.php
+++ b/core/modules/rest/src/Plugin/rest/resource/EntityResourceValidationTrait.php
@@ -3,6 +3,8 @@
 namespace Drupal\rest\Plugin\rest\resource;
 
 use Drupal\Component\Render\PlainTextOutput;
+use Drupal\Core\Entity\EntityConstraintViolationList;
+use Drupal\Core\Entity\EntityConstraintViolationListInterface;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\FieldableEntityInterface;
 use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException;
@@ -23,6 +25,41 @@
    *   If validation errors are found.
    */
   protected function validate(EntityInterface $entity) {
+    if ($violations = $this->doValidation($entity)) {
+      $this->processViolations($violations);
+    }
+  }
+
+  /**
+   * Validates an entity but limits the validation errors to certain fields.
+   *
+   * @param \Drupal\Core\Entity\EntityInterface $entity
+   *   The entity.
+   * @param string[] $changed_fields
+   *   An array of changed fields. If specified filter out the non applying
+   *   violations.
+   *
+   * @throws \Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException
+   *   If validation errors are found.
+   */
+  protected function validateWithFilteredFields(EntityInterface $entity, array $changed_fields) {
+    if ($entity instanceof FieldableEntityInterface && $violations = $this->doValidation($entity)) {
+      $relevant_violations = $violations->getEntityViolations();
+      $relevant_violations->addAll($violations->filterByFields(array_diff(array_keys($entity->getFieldDefinitions()), $changed_fields)));
+      $this->processViolations($relevant_violations);
+    }
+  }
+
+
+  /**
+   * Executes validation for an entity and returns the violations.
+   *
+   * @param \Drupal\Core\Entity\EntityInterface $entity
+   *   The entity to validate.
+   *
+   * @return \Drupal\Core\Entity\EntityConstraintViolationListInterface|null
+   */
+  protected function doValidation(EntityInterface $entity) {
     // @todo Remove when https://www.drupal.org/node/2164373 is committed.
     if (!$entity instanceof FieldableEntityInterface) {
       return;
@@ -33,6 +70,16 @@ protected function validate(EntityInterface $entity) {
     // changes.
     $violations->filterByFieldAccess();
 
+    return $violations;
+  }
+
+  /**
+   * Processes violations by throwing an exception with a helpful error message.
+   *
+   * @param \Drupal\Core\Entity\EntityConstraintViolationListInterface $violations
+   *   The violations to process.
+   */
+  protected function processViolations(EntityConstraintViolationListInterface $violations) {
     if ($violations->count() > 0) {
       $message = "Unprocessable Entity: validation failed.\n";
       foreach ($violations as $violation) {
diff --git a/core/modules/rest/tests/modules/rest_test/rest_test.module b/core/modules/rest/tests/modules/rest_test/rest_test.module
index 7df2863..63393a5 100644
--- a/core/modules/rest/tests/modules/rest_test/rest_test.module
+++ b/core/modules/rest/tests/modules/rest_test/rest_test.module
@@ -5,6 +5,8 @@
  * Contains hook implementations for testing REST module.
  */
 
+use Drupal\Core\Entity\EntityTypeInterface;
+use Drupal\Core\Field\BaseFieldDefinition;
 use Drupal\Core\Field\FieldDefinitionInterface;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\Field\FieldItemListInterface;
@@ -30,3 +32,16 @@ function rest_test_entity_field_access($operation, FieldDefinitionInterface $fie
   // No opinion.
   return AccessResult::neutral();
 }
+
+/**
+ * Implements hook_entity_base_field_info().
+ */
+function rest_test_entity_base_field_info(EntityTypeInterface $entity_type) {
+  $fields = [];
+  $fields['rest_test_validation'] = BaseFieldDefinition::create('string')
+    ->setLabel(t('REST test validation field'))
+    ->setDescription(t('A text field with some special validations attached used for testing purposes'))
+    ->addConstraint('rest_test_validation');
+
+  return $fields;
+}
diff --git a/core/modules/rest/tests/modules/rest_test/src/Plugin/Validation/Constraint/RestTestConstraint.php b/core/modules/rest/tests/modules/rest_test/src/Plugin/Validation/Constraint/RestTestConstraint.php
new file mode 100644
index 0000000..ab4f1fe
--- /dev/null
+++ b/core/modules/rest/tests/modules/rest_test/src/Plugin/Validation/Constraint/RestTestConstraint.php
@@ -0,0 +1,21 @@
+<?php
+
+namespace Drupal\rest_test\Plugin\Validation\Constraint;
+
+use Symfony\Component\Validator\Constraint;
+
+/**
+ * Adds some validations for a REST test field.
+ *
+ * @Constraint(
+ *   id = "rest_test_validation",
+ *   label = @Translation("REST test validation", context = "Validation")
+ * )
+ *
+ * @see \Drupal\Core\TypedData\OptionsProviderInterface
+ */
+class RestTestConstraint extends Constraint {
+
+  public $message = 'REST test validation failed';
+
+}
diff --git a/core/modules/rest/tests/modules/rest_test/src/Plugin/Validation/Constraint/RestTestConstraintValidator.php b/core/modules/rest/tests/modules/rest_test/src/Plugin/Validation/Constraint/RestTestConstraintValidator.php
new file mode 100644
index 0000000..e71c148
--- /dev/null
+++ b/core/modules/rest/tests/modules/rest_test/src/Plugin/Validation/Constraint/RestTestConstraintValidator.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace Drupal\rest_test\Plugin\Validation\Constraint;
+
+use Drupal\Core\Field\FieldItemListInterface;
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+
+/**
+ * Validator for \Drupal\rest_test\Plugin\Validation\Constraint\RestTestConstraint.
+ */
+class RestTestConstraintValidator extends ConstraintValidator {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validate($value, Constraint $constraint) {
+    if ($value instanceof FieldItemListInterface) {
+      $value = $value->getValue();
+      if (!empty($value[0]['value']) && $value[0]['value'] === 'ALWAYS_FAIL') {
+        $this->context->addViolation($constraint->message);
+      }
+    }
+  }
+
+}
diff --git a/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php
index a55ae92..ca735f4 100644
--- a/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php
+++ b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php
@@ -179,6 +179,7 @@ public function setUp() {
 
       // Set a default value on the field.
       $this->entity->set('field_rest_test', ['value' => 'All the faith he had had had had no effect on the outcome of his life.']);
+      $this->entity->set('rest_test_validation', ['value' => 'allowed value']);
       $this->entity->save();
     }
   }
@@ -411,10 +412,20 @@ public function testGet() {
     // for the keys with the array order the same (it needs to match with
     // identical comparison).
     $expected = $this->getExpectedNormalizedEntity();
+    if ($this->entity instanceof FieldableEntityInterface) {
+      $expected += [
+        'rest_test_validation' => [
+          [
+            'value' => 'allowed value',
+          ],
+        ]
+      ];
+    }
+
     ksort($expected);
     $actual = $this->serializer->decode((string) $response->getBody(), static::$format);
     ksort($actual);
-    $this->assertSame($expected, $actual);
+    $this->assertEquals($expected, $actual);
 
     // Not only assert the normalization, also assert deserialization of the
     // response results in the expected object.
@@ -471,6 +482,15 @@ public function testGet() {
       // normalized entity's values to strings. This ensures the BC layer for
       // bc_primitives_as_strings works as expected.
       $expected = $this->getExpectedNormalizedEntity();
+      if ($this->entity instanceof FieldableEntityInterface) {
+        $expected += [
+          'rest_test_validation' => [
+            [
+              'value' => 'allowed value',
+            ],
+          ]
+        ];
+      }
       // Config entities are not affected.
       // @see \Drupal\serialization\Normalizer\ConfigEntityNormalizer::normalize()
       $expected = static::castToString($expected);
@@ -909,9 +929,26 @@ public function testPatch() {
       $this->assertResourceErrorResponse(403, "Access denied on updating field '$field_name'.", $response);
     }
 
+    if ($this->entity instanceof FieldableEntityInterface) {
+      // Set the rest_test_validation field to always fail validation, which
+      // allows asserting that not modifying that field does not trigger
+      // validation errors.
+      $this->entity->set('rest_test_validation', 'ALWAYS_FAIL');
+      $this->entity->save();
+
+      // Change the rest_test_validation field to prove that then its validation
+      // does run. In subsequent test assertions, it will not be modified, and
+      // then should not trigger validation errors.
+      $max_normalization = $this->getNormalizedPatchEntity() + $this->serializer->normalize($this->entity, static::$format);
+      $max_normalization = $this->removeFieldsFromNormalization($max_normalization, static::$patchProtectedFieldNames);
+      $request_options[RequestOptions::BODY] = $this->serializer->serialize($max_normalization, static::$format);
+      $response = $this->request('PATCH', $url, $request_options);
+      $this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\nrest_test_validation: REST test validation failed\n", $response);
+    }
+
     // 200 for well-formed request that sends the maximum number of fields.
     $max_normalization = $this->getNormalizedPatchEntity() + $this->serializer->normalize($this->entity, static::$format);
-    $max_normalization = $this->removeFieldsFromNormalization($max_normalization, static::$patchProtectedFieldNames);
+    $max_normalization = $this->removeFieldsFromNormalization($max_normalization, array_merge(['rest_test_validation'], static::$patchProtectedFieldNames));
     $request_options[RequestOptions::BODY] = $this->serializer->serialize($max_normalization, static::$format);
     $response = $this->request('PATCH', $url, $request_options);
     $this->assertResourceResponse(200, FALSE, $response);
