diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
index d4945cf..b9877bf 100644
--- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
+++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
@@ -551,6 +551,7 @@ protected function loadFromSharedTables(array &$values, array &$translations) {
         $all_fields = $table_mapping->getFieldNames($this->dataTable);
       }
 
+      $storage_definitions = $this->entityManager->getFieldStorageDefinitions($this->entityTypeId);
       $result = $query->execute();
       foreach ($result as $row) {
         $id = $row[$this->idKey];
@@ -562,14 +563,19 @@ protected function loadFromSharedTables(array &$values, array &$translations) {
         $translations[$id][$langcode] = TRUE;
 
         foreach ($all_fields as $field_name) {
+          $storage_definition = $storage_definitions[$field_name];
+          $definition_columns = $storage_definition->getColumns();
           $columns = $table_mapping->getColumnNames($field_name);
           // Do not key single-column fields by property name.
           if (count($columns) == 1) {
-            $values[$id][$field_name][$langcode] = $row[reset($columns)];
+            $column_name = reset($columns);
+            $column_attributes = $definition_columns[key($columns)];
+            $values[$id][$field_name][$langcode] = (!empty($column_attributes['serialize'])) ? unserialize($row[$column_name]) : $row[$column_name];
           }
           else {
             foreach ($columns as $property_name => $column_name) {
-              $values[$id][$field_name][$langcode][$property_name] = $row[$column_name];
+              $column_attributes = $definition_columns[$property_name];
+              $values[$id][$field_name][$langcode][$property_name] = (!empty($column_attributes['serialize'])) ? unserialize($row[$column_name]) : $row[$column_name];
             }
           }
         }
diff --git a/core/modules/field/tests/modules/field_test/src/Plugin/Field/FieldType/TestObjectItem.php b/core/modules/field/tests/modules/field_test/src/Plugin/Field/FieldType/TestObjectItem.php
index a20265e..d5647c2 100644
--- a/core/modules/field/tests/modules/field_test/src/Plugin/Field/FieldType/TestObjectItem.php
+++ b/core/modules/field/tests/modules/field_test/src/Plugin/Field/FieldType/TestObjectItem.php
@@ -46,17 +46,4 @@ public static function schema(FieldStorageDefinitionInterface $field_definition)
     ];
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function setValue($values, $notify = TRUE) {
-    if (isset($values['value'])) {
-      // @todo Remove this in https://www.drupal.org/node/2788637.
-      if (is_string($values['value'])) {
-        $values['value'] = unserialize($values['value']);
-      }
-    }
-    parent::setValue($values, $notify);
-  }
-
 }
diff --git a/core/modules/link/src/Plugin/Field/FieldType/LinkItem.php b/core/modules/link/src/Plugin/Field/FieldType/LinkItem.php
index 6e98ae2..84bf27c 100644
--- a/core/modules/link/src/Plugin/Field/FieldType/LinkItem.php
+++ b/core/modules/link/src/Plugin/Field/FieldType/LinkItem.php
@@ -186,13 +186,6 @@ public function setValue($values, $notify = TRUE) {
         'options' => [],
       ];
     }
-    // Unserialize the values.
-    // @todo The storage controller should take care of this, see
-    //   SqlContentEntityStorage::loadFieldItems, see
-    //   https://www.drupal.org/node/2414835
-    if (is_string($values['options'])) {
-      $values['options'] = unserialize($values['options']);
-    }
     parent::setValue($values, $notify);
   }
 
diff --git a/core/modules/link/tests/src/Kernel/LinkItemTest.php b/core/modules/link/tests/src/Kernel/LinkItemTest.php
index 5e2c45d..968b8f7 100644
--- a/core/modules/link/tests/src/Kernel/LinkItemTest.php
+++ b/core/modules/link/tests/src/Kernel/LinkItemTest.php
@@ -138,11 +138,11 @@ public function testLinkItem() {
     $this->assertNull($entity->field_test->title);
     $this->assertIdentical($entity->field_test->options, []);
 
-    // Check that if set uri and serialize options then the default values are
+    // Check that if we set uri and options then the default values are
     // properly initialized.
     $entity->field_test = [
       'uri' => 'internal:/node/add',
-      'options' => serialize(['query' => NULL]),
+      'options' => ['query' => NULL],
     ];
     $this->assertEqual($entity->field_test->uri, 'internal:/node/add');
     $this->assertNull($entity->field_test->title);
