diff --git a/core/lib/Drupal/Core/Entity/EntityFormController.php b/core/lib/Drupal/Core/Entity/EntityFormController.php
index bc84d16..acd53c5 100644
--- a/core/lib/Drupal/Core/Entity/EntityFormController.php
+++ b/core/lib/Drupal/Core/Entity/EntityFormController.php
@@ -304,10 +304,13 @@ public function validate(array $form, array &$form_state) {
     // Map errors back to form elements.
     if ($violations) {
       foreach ($violations as $field_name => $field_violations) {
-        $langcode = field_is_translatable($entity->entityType(), field_info_field($field_name)) ? $entity_langcode : Language::LANGCODE_NOT_SPECIFIED;
-        $field_state = field_form_get_state($form['#parents'], $field_name, $langcode, $form_state);
-        $field_state['constraint_violations'] = $field_violations;
-        field_form_set_state($form['#parents'], $field_name, $langcode, $form_state, $field_state);
+        $field = field_info_field($field_name);
+        if ($field) {
+          $langcode = field_is_translatable($entity->entityType(), $field) ? $entity_langcode : Language::LANGCODE_NOT_SPECIFIED;
+          $field_state = field_form_get_state($form['#parents'], $field_name, $langcode, $form_state);
+          $field_state['constraint_violations'] = $field_violations;
+          field_form_set_state($form['#parents'], $field_name, $langcode, $form_state, $field_state);
+        }
       }
 
       field_invoke_method('flagErrors', _field_invoke_widget_target($form_state['form_display']), $entity, $form, $form_state);
@@ -433,15 +436,14 @@ protected function submitEntityLanguage(array $form, array &$form_state) {
       $current_langcode = $this->isDefaultFormLangcode($form_state) ? $form_state['values']['langcode'] : $this->getFormLangcode($form_state);
 
       foreach (field_info_instances($entity_type, $entity->bundle()) as $instance) {
-        $field_name = $instance['field_name'];
+        $field_name = $instance->getFieldName();
         $field = field_info_field($field_name);
 
         if (isset($form[$field_name]['#language'])) {
           $previous_langcode = $form[$field_name]['#language'];
-
           // Handle a possible language change: new language values are inserted,
           // previous ones are deleted.
-          if ($field['translatable'] && $previous_langcode != $current_langcode) {
+          if ($field->translatable && $previous_langcode != $current_langcode) {
             $form_state['values'][$field_name][$current_langcode] = $form_state['values'][$field_name][$previous_langcode];
             $form_state['values'][$field_name][$previous_langcode] = array();
           }
diff --git a/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php b/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php
index e288a21..4073e52 100644
--- a/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php
+++ b/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php
@@ -115,7 +115,8 @@ public function addField($field, $type, $langcode) {
         if ($key < $count) {
           $next = $specifiers[$key + 1];
           // Is this a field column?
-          if (isset($field['columns'][$next]) || in_array($next, Field::getReservedColumns())) {
+          $columns = $field->getColumns();
+          if (isset($columns[$next]) || in_array($next, Field::getReservedColumns())) {
             // Use it.
             $column = $next;
             // Do not process it again.
@@ -149,7 +150,7 @@ public function addField($field, $type, $langcode) {
             // column, i.e. target_id or fid.
             // Otherwise, the code executing the relationship will throw an
             // exception anyways so no need to do it here.
-            if (!$column && isset($propertyDefinitions[$relationship_specifier]) && $entity->{$field['field_name']}->get('entity') instanceof EntityReference) {
+            if (!$column && isset($propertyDefinitions[$relationship_specifier]) && $entity->{$field->getFieldName()}->get('entity') instanceof EntityReference) {
               $column = current(array_keys($propertyDefinitions));
             }
             // Prepare the next index prefix.
@@ -161,7 +162,7 @@ public function addField($field, $type, $langcode) {
           $column = 'value';
         }
         $table = $this->ensureFieldTable($index_prefix, $field, $type, $langcode, $base_table, $entity_id_field, $field_id_field);
-        $sql_column = _field_sql_storage_columnname($field['field_name'], $column);
+        $sql_column = _field_sql_storage_columnname($field->getFieldName(), $column);
       }
       // This is an entity property (non-configurable field).
       else {
@@ -248,10 +249,10 @@ protected function ensureEntityTable($index_prefix, $property, $type, $langcode,
    * @throws \Drupal\Core\Entity\Query\QueryException
    */
   protected function ensureFieldTable($index_prefix, &$field, $type, $langcode, $base_table, $entity_id_field, $field_id_field) {
-    $field_name = $field['field_name'];
+    $field_name = $field->getFieldName();
     if (!isset($this->fieldTables[$index_prefix . $field_name])) {
       $table = $this->sqlQuery->getMetaData('age') == FIELD_LOAD_CURRENT ? _field_sql_storage_tablename($field) : _field_sql_storage_revision_tablename($field);
-      if ($field['cardinality'] != 1) {
+      if ($field->getFieldCardinality() != 1) {
         $this->sqlQuery->addMetaData('simple_query', FALSE);
       }
       $entity_type = $this->sqlQuery->getMetaData('entity_type');
diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/Tests/CustomBlockFieldTest.php b/core/modules/block/custom_block/lib/Drupal/custom_block/Tests/CustomBlockFieldTest.php
index c59b435..81ec043 100644
--- a/core/modules/block/custom_block/lib/Drupal/custom_block/Tests/CustomBlockFieldTest.php
+++ b/core/modules/block/custom_block/lib/Drupal/custom_block/Tests/CustomBlockFieldTest.php
@@ -80,12 +80,12 @@ public function testBlockFields() {
     ));
     $this->instance->save();
     entity_get_form_display('custom_block', 'link', 'default')
-      ->setComponent($this->field['field_name'], array(
+      ->setComponent($this->field->id(), array(
         'type' => 'link_default',
       ))
       ->save();
     entity_get_display('custom_block', 'link', 'default')
-      ->setComponent($this->field['field_name'], array(
+      ->setComponent($this->field->id(), array(
         'type' => 'link',
         'label' => 'hidden',
       ))
@@ -95,8 +95,8 @@ public function testBlockFields() {
     $this->drupalGet('block/add/link');
     $edit = array(
       'info' => $this->randomName(8),
-      $this->field['field_name'] . '[und][0][url]' => 'http://example.com',
-      $this->field['field_name'] . '[und][0][title]' => 'Example.com'
+      $this->field->id() . '[und][0][url]' => 'http://example.com',
+      $this->field->id() . '[und][0][title]' => 'Example.com'
     );
     $this->drupalPost(NULL, $edit, t('Save'));
     $block = entity_load('custom_block', 1);
diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/Tests/CustomBlockTypeTest.php b/core/modules/block/custom_block/lib/Drupal/custom_block/Tests/CustomBlockTypeTest.php
index d5322e1..9f3c0cc 100644
--- a/core/modules/block/custom_block/lib/Drupal/custom_block/Tests/CustomBlockTypeTest.php
+++ b/core/modules/block/custom_block/lib/Drupal/custom_block/Tests/CustomBlockTypeTest.php
@@ -79,7 +79,7 @@ public function testCustomBlockTypeEditing() {
     $this->createCustomBlockType('other');
 
     $instance = field_info_instance('custom_block', 'block_body', 'basic');
-    $this->assertEqual($instance['label'], 'Block body', 'Body field was found.');
+    $this->assertEqual($instance->label(), 'Block body', 'Body field was found.');
 
     // Verify that title and body fields are displayed.
     $this->drupalGet('block/add/basic');
diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentLanguageTest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentLanguageTest.php
index 84a080e..4ae0960 100644
--- a/core/modules/comment/lib/Drupal/comment/Tests/CommentLanguageTest.php
+++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentLanguageTest.php
@@ -72,8 +72,9 @@ function setUp() {
 
     // Make comment body translatable.
     $field = field_info_field('comment_body');
-    $field['translatable'] = TRUE;
+    $field->translatable = TRUE;
     $field->save();
+
     $this->assertTrue(field_is_translatable('comment', $field), 'Comment body is translatable.');
   }
 
diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentTranslationUITest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentTranslationUITest.php
index 5c25660..a0009f3 100644
--- a/core/modules/comment/lib/Drupal/comment/Tests/CommentTranslationUITest.php
+++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentTranslationUITest.php
@@ -64,7 +64,7 @@ protected function getTranslatorPermissions() {
   function setupTestFields() {
     parent::setupTestFields();
     $field = field_info_field('comment_body');
-    $field['translatable'] = TRUE;
+    $field->translatable = TRUE;
     $field->save();
   }
 
diff --git a/core/modules/content_translation/content_translation.admin.inc b/core/modules/content_translation/content_translation.admin.inc
index 97cbfa9..895dc79 100644
--- a/core/modules/content_translation/content_translation.admin.inc
+++ b/core/modules/content_translation/content_translation.admin.inc
@@ -24,11 +24,11 @@
 function content_translation_field_sync_widget(Field $field, FieldInstance $instance) {
   $element = array();
 
-  if (!empty($field['settings']['column_groups']) && count($field['settings']['column_groups']) > 1) {
+  if (!empty($field->settings['column_groups']) && count($field->settings['column_groups']) > 1) {
     $options = array();
     $default = array();
 
-    foreach ($field['settings']['column_groups'] as $group => $info) {
+    foreach ($field->settings['column_groups'] as $group => $info) {
       $options[$group] = $info['label'];
       $default[$group] = !empty($info['translatable']) ? $group : FALSE;
     }
@@ -39,7 +39,7 @@ function content_translation_field_sync_widget(Field $field, FieldInstance $inst
       '#type' => 'checkboxes',
       '#title' => t('Translatable elements'),
       '#options' => $options,
-      '#default_value' => !empty($instance['settings']['translation_sync']) ? $instance['settings']['translation_sync'] : $default,
+      '#default_value' => !empty($instance->settings['translation_sync']) ? $instance->settings['translation_sync'] : $default,
       '#attached' => array(
         'library' => array(
           array('content_translation', 'drupal.content_translation.admin'),
@@ -97,9 +97,9 @@ function _content_translation_form_language_content_settings_form_alter(array &$
           foreach ($fields as $field_name => $instance) {
             $field = field_info_field($field_name);
             $form['settings'][$entity_type][$bundle]['fields'][$field_name] = array(
-              '#label' => $instance['label'],
+              '#label' => $instance->label,
               '#type' => 'checkbox',
-              '#default_value' => $field['translatable'],
+              '#default_value' => $field->translatable,
             );
             $column_element = content_translation_field_sync_widget($field, $instance);
             if ($column_element) {
@@ -337,7 +337,7 @@ function _content_translation_update_field_translatability($settings) {
   $operations = array();
   foreach ($fields as $field_name => $translatable) {
     $field = field_info_field($field_name);
-    if ($field['translatable'] != $translatable) {
+    if ($field->translatable != $translatable) {
       // If a field is untranslatable, it can have no data except under
       // Language::LANGCODE_NOT_SPECIFIED. Thus we need a field to be translatable before
       // we convert data to the entity language. Conversely we need to switch
@@ -379,8 +379,8 @@ function _content_translation_update_field_translatability($settings) {
  */
 function content_translation_translatable_switch($translatable, $field_name) {
   $field = field_info_field($field_name);
-  if ($field['translatable'] !== $translatable) {
-    $field['translatable'] = $translatable;
+  if ($field->translatable !== $translatable) {
+    $field->translatable = $translatable;
     $field->save();
   }
 }
@@ -396,7 +396,8 @@ function content_translation_translatable_switch($translatable, $field_name) {
  */
 function content_translation_translatable_batch($translatable, $field_name, &$context) {
   $field = field_info_field($field_name);
-  $column = isset($field['columns']['value']) ? 'value' : key($field['columns']);
+  $columns = $field->getColumns();
+  $column = isset($columns['value']) ? 'value' : key($columns);
   $query_field = "$field_name.$column";
 
   // Determine the entity types to act on.
diff --git a/core/modules/content_translation/content_translation.module b/core/modules/content_translation/content_translation.module
index 34e918c..625ac2d 100644
--- a/core/modules/content_translation/content_translation.module
+++ b/core/modules/content_translation/content_translation.module
@@ -620,9 +620,9 @@ function content_translation_form_alter(array &$form, array &$form_state) {
       }
       else {
         foreach (field_info_instances($entity->entityType(), $entity->bundle()) as $instance) {
-          $field_name = $instance['field_name'];
+          $field_name = $instance->getFieldName();
           $field = field_info_field($field_name);
-          $form[$field_name]['#multilingual'] = !empty($field['translatable']);
+          $form[$field_name]['#multilingual'] = !empty($field->translatable);
         }
       }
     }
@@ -655,9 +655,9 @@ function content_translation_field_language_alter(&$display_language, $context)
           //   entity language and with Language::LANGCODE_DEFAULT. We need need to unset
           //   both until we remove the BC layer.
           if ($langcode == $entity_langcode) {
-            unset($entity->{$instance['field_name']}[Language::LANGCODE_DEFAULT]);
+            unset($entity->{$instance->getFieldName()}[Language::LANGCODE_DEFAULT]);
           }
-          unset($entity->{$instance['field_name']}[$langcode]);
+          unset($entity->{$instance->getFieldName()}[$langcode]);
         }
       }
     }
@@ -808,8 +808,8 @@ function content_translation_field_extra_fields() {
  */
 function content_translation_form_field_ui_field_edit_form_alter(array &$form, array &$form_state, $form_id) {
   $field = $form['#field'];
-  $field_name = $field['field_name'];
-  $translatable = $field['translatable'];
+  $field_name = $field->id();
+  $translatable = $field->translatable;
   $label = t('Field translation');
 
   if ($field->hasData()) {
@@ -842,7 +842,7 @@ function content_translation_form_field_ui_field_edit_form_alter(array &$form, a
  * Implements hook_form_FORM_ID_alter() for 'field_ui_field_instance_edit_form'.
  */
 function content_translation_form_field_ui_field_instance_edit_form_alter(array &$form, array &$form_state, $form_id) {
-  if ($form['#field']['translatable']) {
+  if ($form['#field']->translatable) {
     module_load_include('inc', 'content_translation', 'content_translation.admin');
     $element = content_translation_field_sync_widget($form['#field'], $form['#instance']);
     if ($element) {
@@ -1024,13 +1024,13 @@ function content_translation_save_settings($settings) {
           foreach ($bundle_settings['columns'] as $field_name => $column_settings) {
             $field = field_info_field($field_name);
             $instance = field_info_instance($entity_type, $field_name, $bundle);
-            if ($field['translatable']) {
-              $instance['settings']['translation_sync'] = $column_settings;
+            if ($field->translatable) {
+              $instance->settings['translation_sync'] = $column_settings;
             }
             // If the field does not have translatable enabled we need to reset
             // the sync settings to their defaults.
             else {
-              unset($instance['settings']['translation_sync']);
+              unset($instance->settings['translation_sync']);
             }
             $instance->save();
           }
diff --git a/core/modules/content_translation/content_translation.pages.inc b/core/modules/content_translation/content_translation.pages.inc
index e277791..b85d049 100644
--- a/core/modules/content_translation/content_translation.pages.inc
+++ b/core/modules/content_translation/content_translation.pages.inc
@@ -40,9 +40,9 @@ function content_translation_overview(EntityInterface $entity) {
     // Determine whether the current entity is translatable.
     $translatable = FALSE;
     foreach (field_info_instances($entity->entityType(), $entity->bundle()) as $instance) {
-      $field_name = $instance['field_name'];
+      $field_name = $instance->getFieldName();
       $field = field_info_field($field_name);
-      if ($field['translatable']) {
+      if ($field->translatable) {
         $translatable = TRUE;
         break;
       }
@@ -247,7 +247,7 @@ function content_translation_prepare_translation(EntityInterface $entity, Langua
     $instances = field_info_instances($entity->entityType(), $entity->bundle());
     foreach ($instances as $field_name => $instance) {
       $field = field_info_field($field_name);
-      if (!empty($field['translatable'])) {
+      if (!empty($field->translatable)) {
         $value = $entity->get($field_name);
         $value[$target->id] = isset($value[$source->id]) ? $value[$source->id] : array();
         $entity->set($field_name, $value);
diff --git a/core/modules/content_translation/lib/Drupal/content_translation/ContentTranslationController.php b/core/modules/content_translation/lib/Drupal/content_translation/ContentTranslationController.php
index 3374ddf..eb3d8df 100644
--- a/core/modules/content_translation/lib/Drupal/content_translation/ContentTranslationController.php
+++ b/core/modules/content_translation/lib/Drupal/content_translation/ContentTranslationController.php
@@ -50,9 +50,9 @@ public function removeTranslation(EntityInterface $entity, $langcode) {
     // @todo Handle properties.
     // Remove field translations.
     foreach (field_info_instances($entity->entityType(), $entity->bundle()) as $instance) {
-      $field_name = $instance['field_name'];
+      $field_name = $instance->getFieldName();
       $field = field_info_field($field_name);
-      if ($field['translatable']) {
+      if ($field->translatable) {
         $entity->{$field_name}[$langcode] = array();
       }
     }
diff --git a/core/modules/content_translation/lib/Drupal/content_translation/FieldTranslationSynchronizer.php b/core/modules/content_translation/lib/Drupal/content_translation/FieldTranslationSynchronizer.php
index 9fd4b0e..0ab6c5f 100644
--- a/core/modules/content_translation/lib/Drupal/content_translation/FieldTranslationSynchronizer.php
+++ b/core/modules/content_translation/lib/Drupal/content_translation/FieldTranslationSynchronizer.php
@@ -66,14 +66,14 @@ public function synchronizeFields(EntityInterface $entity, $sync_langcode, $orig
 
       // Sync when the field is not empty, when the synchronization translations
       // setting is set, and the field is translatable.
-      if (!$entity->get($field_name)->isEmpty() && !empty($instance['settings']['translation_sync']) && field_is_translatable($entity_type, $field)) {
+      if (!$entity->get($field_name)->isEmpty() && !empty($instance->settings['translation_sync']) && field_is_translatable($entity_type, $field)) {
         // Retrieve all the untranslatable column groups and merge them into
         // single list.
-        $groups = array_keys(array_diff($instance['settings']['translation_sync'], array_filter($instance['settings']['translation_sync'])));
+        $groups = array_keys(array_diff($instance->settings['translation_sync'], array_filter($instance->settings['translation_sync'])));
         if (!empty($groups)) {
           $columns = array();
           foreach ($groups as $group) {
-            $info = $field['settings']['column_groups'][$group];
+            $info = $field->settings['column_groups'][$group];
             // A missing 'columns' key indicates we have a single-column group.
             $columns = array_merge($columns, isset($info['columns']) ? $info['columns'] : array($group));
           }
diff --git a/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationSettingsTest.php b/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationSettingsTest.php
index c17bd06..aeb8976 100644
--- a/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationSettingsTest.php
+++ b/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationSettingsTest.php
@@ -90,7 +90,7 @@ function testSettingsUI() {
     $this->assertSettings('comment', 'comment_node_article', TRUE, $edit);
     field_info_cache_clear();
     $field = field_info_field('comment_body');
-    $this->assertTrue($field['translatable'], 'Comment body is translatable.');
+    $this->assertTrue($field->translatable, 'Comment body is translatable.');
 
     // Test that language settings are correctly stored.
     $language_configuration = language_get_default_configuration('comment', 'comment_node_article');
diff --git a/core/modules/datetime/datetime.module b/core/modules/datetime/datetime.module
index 0da06cb..9ee20e1 100644
--- a/core/modules/datetime/datetime.module
+++ b/core/modules/datetime/datetime.module
@@ -190,11 +190,11 @@ function datetime_default_value($entity, $field, $instance, $langcode) {
 
   $value = '';
   $date = '';
-  if ($instance['settings']['default_value'] == 'now') {
+  if ($instance->settings['default_value'] == 'now') {
     // A default value should be in the format and timezone used for date
     // storage.
     $date = new DrupalDateTime('now', DATETIME_STORAGE_TIMEZONE);
-    $storage_format = $field['settings']['datetime_type'] == 'date' ? DATETIME_DATE_STORAGE_FORMAT: DATETIME_DATETIME_STORAGE_FORMAT;
+    $storage_format = $field->settings['datetime_type'] == 'date' ? DATETIME_DATE_STORAGE_FORMAT: DATETIME_DATETIME_STORAGE_FORMAT;
     $value = $date->format($storage_format);
   }
 
diff --git a/core/modules/datetime/lib/Drupal/datetime/Tests/DateTimeItemTest.php b/core/modules/datetime/lib/Drupal/datetime/Tests/DateTimeItemTest.php
index 16731a2..c30ba25 100644
--- a/core/modules/datetime/lib/Drupal/datetime/Tests/DateTimeItemTest.php
+++ b/core/modules/datetime/lib/Drupal/datetime/Tests/DateTimeItemTest.php
@@ -42,7 +42,7 @@ public function setUp() {
     ));
     $this->field->save();
     $this->instance = entity_create('field_instance', array(
-      'field_name' => $this->field['field_name'],
+      'field_name' => $this->field->getFieldName(),
       'entity_type' => 'entity_test',
       'bundle' => 'entity_test',
       'settings' => array(
diff --git a/core/modules/datetime/lib/Drupal/datetime/Tests/DatetimeFieldTest.php b/core/modules/datetime/lib/Drupal/datetime/Tests/DatetimeFieldTest.php
index 867e67d..ea695f2 100644
--- a/core/modules/datetime/lib/Drupal/datetime/Tests/DatetimeFieldTest.php
+++ b/core/modules/datetime/lib/Drupal/datetime/Tests/DatetimeFieldTest.php
@@ -162,7 +162,7 @@ function testDateField() {
   function testDatetimeField() {
     $field_name = $this->field->id();
     // Change the field to a datetime field.
-    $this->field['settings']['datetime_type'] = 'datetime';
+    $this->field->settings['datetime_type'] = 'datetime';
     $this->field->save();
 
     // Display creation form.
diff --git a/core/modules/edit/lib/Drupal/edit/Form/EditFieldForm.php b/core/modules/edit/lib/Drupal/edit/Form/EditFieldForm.php
index cdeeb0d..c3437b2 100644
--- a/core/modules/edit/lib/Drupal/edit/Form/EditFieldForm.php
+++ b/core/modules/edit/lib/Drupal/edit/Form/EditFieldForm.php
@@ -115,7 +115,7 @@ protected function buildEntity(array $form, array &$form_state) {
     //   types: http://drupal.org/node/1678002.
     if ($entity->entityType() == 'node' && $entity->isNewRevision() && !isset($entity->log)) {
       $instance = field_info_instance($entity->entityType(), $form_state['field_name'], $entity->bundle());
-      $entity->log = t('Updated the %field-name field through in-place editing.', array('%field-name' => $instance['label']));
+      $entity->log = t('Updated the %field-name field through in-place editing.', array('%field-name' => $instance->label()));
     }
 
     return $entity;
diff --git a/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php b/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php
index 6a1c9de..bdbcdf3 100644
--- a/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php
+++ b/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php
@@ -209,8 +209,8 @@ public function setComponent($name, array $options = array()) {
     }
 
     if ($instance = field_info_instance($this->targetEntityType, $name, $this->bundle)) {
-      $field = field_info_field($instance['field_name']);
-      $options = $this->pluginManager->prepareConfiguration($field['type'], $options);
+      $field = field_info_field($instance->getFieldName());
+      $options = $this->pluginManager->prepareConfiguration($field->type, $options);
 
       // Clear the persisted plugin, if any.
       unset($this->plugins[$name]);
diff --git a/core/modules/entity_reference/entity_reference.module b/core/modules/entity_reference/entity_reference.module
index 4d1554d..495e17f 100644
--- a/core/modules/entity_reference/entity_reference.module
+++ b/core/modules/entity_reference/entity_reference.module
@@ -38,14 +38,14 @@ function entity_reference_entity_field_info_alter(&$info, $entity_type) {
   foreach (field_info_instances($entity_type) as $bundle_name => $instances) {
     foreach ($instances as $field_name => $instance) {
       $field = field_info_field($field_name);
-      if ($field['type'] != 'entity_reference') {
+      if ($field->getFieldType() != 'entity_reference') {
         continue;
       }
       if (isset($info['definitions'][$field_name])) {
-        $info['definitions'][$field_name]['settings']['target_type'] = $field['settings']['target_type'];
+        $info['definitions'][$field_name]['settings']['target_type'] = $field->settings['target_type'];
       }
       elseif (isset($info['optional'][$field_name])) {
-        $info['optional'][$field_name]['settings']['target_type'] = $field['settings']['target_type'];
+        $info['optional'][$field_name]['settings']['target_type'] = $field->settings['target_type'];
       }
     }
   }
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceAutocomplete.php b/core/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceAutocomplete.php
index 492fa25..8fa080c 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceAutocomplete.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceAutocomplete.php
@@ -85,7 +85,7 @@ public function getMatches($field, $instance, $entity_type, $entity_id = '', $pr
 
     if (isset($string)) {
       // Get an array of matching entities.
-      $widget = entity_get_form_display($instance['entity_type'], $instance['bundle'], 'default')->getComponent($instance['field_name']);
+      $widget = entity_get_form_display($instance->entity_type, $instance->bundle, 'default')->getComponent($instance->getFieldName());
       $match_operator = !empty($widget['settings']['match_operator']) ? $widget['settings']['match_operator'] : 'CONTAINS';
       $entity_labels = $handler->getReferenceableEntities($string, $match_operator, 10);
 
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceController.php b/core/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceController.php
index b6099f1..252e301 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceController.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceController.php
@@ -77,7 +77,7 @@ public function handleAutocomplete(Request $request, $type, $field_name, $entity
       throw new AccessDeniedHttpException();
     }
 
-    if ($field['type'] != 'entity_reference' || !field_access('edit', $field, $entity_type)) {
+    if ($field->type != 'entity_reference' || !field_access('edit', $field, $entity_type)) {
       throw new AccessDeniedHttpException();
     }
 
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/field_type/ConfigurableEntityReferenceItem.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/field_type/ConfigurableEntityReferenceItem.php
index 786f0da..deaa32c 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/field_type/ConfigurableEntityReferenceItem.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/field_type/ConfigurableEntityReferenceItem.php
@@ -68,8 +68,8 @@ public static function schema(FieldInterface $field) {
 
     // Create a foreign key to the target entity type base type.
     $entity_manager = \Drupal::service('plugin.manager.entity');
-    if (is_subclass_of($entity_manager->getControllerClass($field['settings']['target_type'], 'storage'), 'Drupal\Core\Entity\DatabaseStorageController')) {
-      $entity_info = $entity_manager->getDefinition($field['settings']['target_type']);
+    if (is_subclass_of($entity_manager->getControllerClass($field->settings['target_type'], 'storage'), 'Drupal\Core\Entity\DatabaseStorageController')) {
+      $entity_info = $entity_manager->getDefinition($field->settings['target_type']);
 
       $base_table = $entity_info['base_table'];
       $id_column = $entity_info['entity_keys']['id'];
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceItemTest.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceItemTest.php
index 8c17fd6..4539f13 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceItemTest.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceItemTest.php
@@ -119,7 +119,7 @@ public function testEntityReferenceFieldSchema() {
     $this->assertEqual(count($schema['foreign keys']), 1, 'There is 1 foreign key in the schema.');
 
     $foreign_key = reset($schema['foreign keys']);
-    $foreign_key_column = _field_sql_storage_columnname($field['field_name'], $foreign_key_column_name);
+    $foreign_key_column = _field_sql_storage_columnname($field->id(), $foreign_key_column_name);
     $this->assertEqual($foreign_key['table'], 'taxonomy_term_data', 'Foreign key table name preserved in the schema.');
     $this->assertEqual($foreign_key['columns'][$foreign_key_column], 'tid', 'Foreign key column name preserved in the schema.');
 
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionSortTest.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionSortTest.php
index b44c54d..14ed6f1 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionSortTest.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionSortTest.php
@@ -133,7 +133,7 @@ public function testSort() {
     $this->assertIdentical($result['article'], $expected_result, 'Query sorted by field returned expected values.');
 
     // Assert sort by property.
-    $instance['settings']['handler_settings']['sort'] = array(
+    $instance->settings['handler_settings']['sort'] = array(
       'field' => 'nid',
       'direction' => 'ASC',
     );
diff --git a/core/modules/field/field.api.php b/core/modules/field/field.api.php
index 9deadaf..a0bd442 100644
--- a/core/modules/field/field.api.php
+++ b/core/modules/field/field.api.php
@@ -809,8 +809,8 @@ function hook_field_storage_write(\Drupal\Core\Entity\EntityInterface $entity, $
  */
 function hook_field_storage_delete(\Drupal\Core\Entity\EntityInterface $entity, $fields) {
   foreach (field_info_instances($entity->entityType(), $entity->bundle()) as $instance) {
-    if (isset($fields[$instance['field_id']])) {
-      $field = field_info_field_by_id($instance['field_id']);
+    if (isset($fields[$instance->getField()->uuid])) {
+      $field = field_info_field_by_id($instance->getField()->uuid);
       field_sql_storage_field_storage_purge($entity, $field, $instance);
     }
   }
diff --git a/core/modules/field/field.attach.inc b/core/modules/field/field.attach.inc
index 3125584..81ecdd2 100644
--- a/core/modules/field/field.attach.inc
+++ b/core/modules/field/field.attach.inc
@@ -166,8 +166,8 @@ function field_invoke_method($method, $target_function, EntityInterface $entity,
     $target = call_user_func($target_function, $instance);
 
     if (method_exists($target, $method)) {
-      $field = field_info_field_by_id($instance['field_id']);
-      $field_name = $field['field_name'];
+      $field = field_info_field_by_id($instance->getField()->uuid());
+      $field_name = $field->getFieldName();
 
       // Determine the list of languages to iterate on.
       $available_langcodes = field_available_languages($entity_type, $field);
@@ -256,8 +256,8 @@ function field_invoke_method_multiple($method, $target_function, array $entities
     $entity_instances = _field_invoke_get_instances($entity_type, $entity->bundle(), $options);
 
     foreach ($entity_instances as $instance) {
-      $instance_id = $instance['id'];
-      $field_name = $instance['field_name'];
+      $instance_id = $instance->id();
+      $field_name = $instance->getFieldName();
 
       // Let the closure determine the target object on which the method should
       // be called.
@@ -273,7 +273,7 @@ function field_invoke_method_multiple($method, $target_function, array $entities
 
         // Unless a language code suggestion is provided we iterate on all the
         // available language codes.
-        $field = field_info_field_by_id($instance['field_id']);
+        $field = field_info_field_by_id($instance->getField()->uuid());
         $available_langcodes = field_available_languages($entity_type, $field);
         $langcode = !empty($options['langcode'][$id]) ? $options['langcode'][$id] : $options['langcode'];
         $langcodes = _field_language_suggestion($available_langcodes, $langcode, $field_name);
@@ -292,7 +292,7 @@ function field_invoke_method_multiple($method, $target_function, array $entities
 
   // For each instance, invoke the method and collect results.
   foreach ($instances as $instance_id => $instance) {
-    $field_name = $instance['field_name'];
+    $field_name = $instance->getFieldName();
 
     // Iterate over all the field translations.
     foreach ($grouped_items[$instance_id] as $langcode => $items) {
@@ -386,7 +386,7 @@ function _field_invoke_get_instances($entity_type, $bundle, $options) {
  */
 function _field_invoke_widget_target($form_display) {
   return function ($instance) use ($form_display) {
-    return $form_display->getRenderer($instance['field_name']);
+    return $form_display->getRenderer($instance->getFieldName());
   };
 }
 
@@ -410,7 +410,7 @@ function field_attach_preprocess(EntityInterface $entity, $element, &$variables)
   // Ensure we are working with a BC mode entity.
   $entity = $entity->getBCEntity();
   foreach (field_info_instances($entity->entityType(), $entity->bundle()) as $instance) {
-    $field_name = $instance['field_name'];
+    $field_name = $instance->getFieldName();
     if (isset($element[$field_name]['#language'])) {
       $langcode = $element[$field_name]['#language'];
       $variables[$field_name] = isset($entity->{$field_name}[$langcode]) ? $entity->{$field_name}[$langcode] : NULL;
diff --git a/core/modules/field/field.default.inc b/core/modules/field/field.default.inc
new file mode 100644
index 0000000..0bcd490
--- /dev/null
+++ b/core/modules/field/field.default.inc
@@ -0,0 +1,85 @@
+<?php
+
+use Drupal\Core\Entity\EntityInterface;
+
+/**
+ * @file
+ * Default 'implementations' of hook_field_*(): common field housekeeping.
+ *
+ * Those implementations are special, as field.module does not define any field
+ * types. Those functions take care of default stuff common to all field types.
+ * They are called through the _field_invoke_default() iterator, generally in
+ * the corresponding field_attach_[operation]() function.
+ */
+
+use Drupal\Core\Language\Language;
+
+/**
+ * Generic field validation handler.
+ *
+ * Possible error codes:
+ * - 'field_cardinality': The number of values exceeds the field cardinality.
+ *
+ * @see _hook_field_validate()
+ *
+ * @param \Drupal\Core\Entity\EntityInterface $entity
+ *   The entity for the operation.
+ * @param $field
+ *   The field structure for the operation.
+ * @param $instance
+ *   The instance structure for $field in $entity's bundle.
+ * @param $langcode
+ *   The language associated with $items.
+ * @param $items
+ *   $entity->{$field->id()}[$langcode], or an empty array if unset.
+ * @param $errors
+ *   The array of errors, keyed by field name and by value delta, that have
+ *   already been reported for the entity. The function should add its errors to
+ *   this array. Each error is an associative array, with the following keys and
+ *   values:
+ *   - error: An error code (should be a string, prefixed with the module name).
+ *   - message: The human readable message to be displayed.
+ */
+function field_default_validate(EntityInterface $entity, $field, $instance, $langcode, $items, &$errors) {
+  // Filter out empty values.
+  $items = _field_filter_items($field->type, $items);
+
+  // Check that the number of values doesn't exceed the field cardinality.
+  // For form submitted values, this can only happen with 'multiple value'
+  // widgets.
+  if ($field->cardinality != FIELD_CARDINALITY_UNLIMITED && count($items) > $field->cardinality) {
+    $errors[$field->id()][$langcode][0][] = array(
+      'error' => 'field_cardinality',
+      'message' => t('%name: this field cannot hold more than @count values.', array('%name' => $instance->label(), '@count' => $field->cardinality)),
+    );
+  }
+}
+
+/**
+ * Copies source field values into the entity to be prepared.
+ *
+ * @param \Drupal\Core\Entity\EntityInterface $entity
+ *   The entity to be prepared for translation.
+ * @param $field
+ *   The field structure for the operation.
+ * @param $instance
+ *   The instance structure for $field in $entity's bundle.
+ * @param $langcode
+ *   The language the entity has to be translated to.
+ * @param $items
+ *   $entity->{$field->id()}[$langcode], or an empty array if unset.
+ * @param \Drupal\Core\Entity\EntityInterface $source_entity
+ *   The source entity holding the field values to be translated.
+ * @param $source_langcode
+ *   The source language from which to translate.
+ */
+function field_default_prepare_translation(EntityInterface $entity, $field, $instance, $langcode, &$items, EntityInterface $source_entity, $source_langcode) {
+  $field_name = $field->id();
+  // If the field is untranslatable keep using Language::LANGCODE_NOT_SPECIFIED.
+  if ($langcode == Language::LANGCODE_NOT_SPECIFIED) {
+    $source_langcode = Language::LANGCODE_NOT_SPECIFIED;
+  }
+  if (isset($source_entity->{$field_name}[$source_langcode])) {
+    $items = $source_entity->{$field_name}[$source_langcode];
+  }
+}
diff --git a/core/modules/field/field.deprecated.inc b/core/modules/field/field.deprecated.inc
index 1b1d8f9..1776a46 100644
--- a/core/modules/field/field.deprecated.inc
+++ b/core/modules/field/field.deprecated.inc
@@ -755,7 +755,7 @@ function field_attach_load($entity_type, $entities, $age = FIELD_LOAD_CURRENT, $
         $data = array();
         $instances = field_info_instances($entity_type, $entity->bundle());
         foreach ($instances as $instance) {
-          $data[$instance['field_name']] = $queried_entities[$id]->{$instance['field_name']};
+          $data[$instance->getFieldName()] = $queried_entities[$id]->{$instance->getFieldName()};
         }
         $cid = "field:$entity_type:$id";
         cache('field')->set($cid, $data);
@@ -919,13 +919,13 @@ function field_attach_insert(EntityInterface $entity) {
   // Collect the storage backends used by the remaining fields in the entities.
   $storages = array();
   foreach (field_info_instances($entity->entityType(), $entity->bundle()) as $instance) {
-    $field = field_info_field_by_id($instance['field_id']);
-    $field_id = $field['uuid'];
-    $field_name = $field['field_name'];
+    $field = field_info_field_by_id($instance->getField()->uuid());
+    $field_id = $field->uuid();
+    $field_name = $field->id();
     if (!empty($entity->$field_name)) {
       // Collect the storage backend if the field has not been written yet.
       if (!isset($skip_fields[$field_id])) {
-        $storages[$field['storage']['type']][$field_id] = $field_id;
+        $storages[$field->storage['type']][$field_id] = $field_id;
       }
     }
   }
@@ -960,11 +960,11 @@ function field_attach_update(EntityInterface $entity) {
   // Collect the storage backends used by the remaining fields in the entities.
   $storages = array();
   foreach (field_info_instances($entity->entityType(), $entity->bundle()) as $instance) {
-    $field = field_info_field_by_id($instance['field_id']);
-    $field_id = $field['uuid'];
+    $field = field_info_field_by_id($instance->getField()->uuid());
+    $field_id = $field->uuid();
     // Collect the storage backend if the field has not been written yet.
     if (!isset($skip_fields[$field_id])) {
-      $storages[$field['storage']['type']][$field_id] = $field_id;
+      $storages[$field->storage['type']][$field_id] = $field_id;
     }
   }
 
@@ -996,9 +996,9 @@ function field_attach_delete(EntityInterface $entity) {
   // Collect the storage backends used by the fields in the entities.
   $storages = array();
   foreach (field_info_instances($entity->entityType(), $entity->bundle()) as $instance) {
-    $field = field_info_field_by_id($instance['field_id']);
-    $field_id = $field['uuid'];
-    $storages[$field['storage']['type']][$field_id] = $field_id;
+    $field = field_info_field_by_id($instance->getField()->uuid());
+    $field_id = $field->uuid();
+    $storages[$field->storage['type']][$field_id] = $field_id;
   }
 
   // Field storage backends delete their data.
@@ -1029,9 +1029,9 @@ function field_attach_delete_revision(EntityInterface $entity) {
   // Collect the storage backends used by the fields in the entities.
   $storages = array();
   foreach (field_info_instances($entity->entityType(), $entity->bundle()) as $instance) {
-    $field = field_info_field_by_id($instance['field_id']);
-    $field_id = $field['uuid'];
-    $storages[$field['storage']['type']][$field_id] = $field_id;
+    $field = field_info_field_by_id($instance->getField()->uuid());
+    $field_id = $field->uuid();
+    $storages[$field->storage['type']][$field_id] = $field_id;
   }
 
   // Field storage backends delete their data.
@@ -1095,8 +1095,8 @@ function field_attach_prepare_view($entity_type, array $entities, array $display
   // instance, call the prepareView() method on the formatter object handed by
   // the entity display.
   $target_function = function ($instance) use ($displays) {
-    if (isset($displays[$instance['bundle']])) {
-      return $displays[$instance['bundle']]->getRenderer($instance['field_name']);
+    if (isset($displays[$instance->bundle])) {
+      return $displays[$instance->bundle]->getRenderer($instance->getFieldName());
     }
   };
   $null = NULL;
@@ -1141,7 +1141,7 @@ function field_attach_view(EntityInterface $entity, EntityDisplay $display, $lan
   // For each instance, call the view() method on the formatter object handed
   // by the entity display.
   $target_function = function ($instance) use ($display) {
-    return $display->getRenderer($instance['field_name']);
+    return $display->getRenderer($instance->getFieldName());
   };
   $null = NULL;
   $output = field_invoke_method('view', $target_function, $entity, $null, $null, $options);
diff --git a/core/modules/field/field.info.inc b/core/modules/field/field.info.inc
index f32fb95..21e7d66 100644
--- a/core/modules/field/field.info.inc
+++ b/core/modules/field/field.info.inc
@@ -128,7 +128,7 @@ function _field_info_collate_types_reset() {
  */
 function field_behaviors_widget($op, $instance) {
   $info = array();
-  if ($component = entity_get_form_display($instance['entity_type'], $instance['bundle'], 'default')->getComponent($instance['field_name'])) {
+  if ($component = entity_get_form_display($instance->entity_type, $instance->bundle, 'default')->getComponent($instance->getFieldName())) {
     $info = \Drupal::service('plugin.manager.field.widget')->getDefinition($component['type']);
   }
   return isset($info[$op]) ? $info[$op] : FIELD_BEHAVIOR_DEFAULT;
@@ -182,8 +182,8 @@ function field_info_fields() {
 
   $fields = array();
   foreach ($info as $key => $field) {
-    if (!$field['deleted']) {
-      $fields[$field['field_name']] = $field;
+    if (!$field->deleted) {
+      $fields[$field->getFieldName()] = $field;
     }
   }
 
diff --git a/core/modules/field/field.module b/core/modules/field/field.module
index c355e67..5d5898a 100644
--- a/core/modules/field/field.module
+++ b/core/modules/field/field.module
@@ -212,7 +212,7 @@ function field_system_info_alter(&$info, $file, $type) {
       // remains no actual, non-deleted fields)
       $non_deleted = FALSE;
       foreach ($fields as $field) {
-        if (empty($field['deleted'])) {
+        if (empty($field->deleted)) {
           $non_deleted = TRUE;
           break;
         }
@@ -308,7 +308,7 @@ function field_entity_bundle_rename($entity_type, $bundle_old, $bundle_new) {
   $instances = field_read_instances();
   foreach ($instances as $instance) {
     if ($instance->entity_type == $entity_type && $instance->bundle == $bundle_old) {
-      $id_new = $instance['entity_type'] . '.' . $bundle_new . '.' . $instance['field_name'];
+      $id_new = $instance->entity_type . '.' . $bundle_new . '.' . $instance->getFieldName();
       $instance->id = $id_new;
       $instance->bundle = $bundle_new;
       $instance->allowBundleRename();
@@ -733,7 +733,7 @@ function field_view_field(EntityInterface $entity, $field_name, $display_options
     // $display_options, so we cannot let preparation happen internally.
     $field = field_info_field($field_name);
     $formatter_manager = drupal_container()->get('plugin.manager.field.formatter');
-    $display_options = $formatter_manager->prepareConfiguration($field['type'], $display_options);
+    $display_options = $formatter_manager->prepareConfiguration($field->getFieldType(), $display_options);
     $formatter = $formatter_manager->getInstance(array(
       'field_definition' => $instance,
       'view_mode' => $view_mode,
diff --git a/core/modules/field/field.multilingual.inc b/core/modules/field/field.multilingual.inc
index d02595c..f087d7f 100644
--- a/core/modules/field/field.multilingual.inc
+++ b/core/modules/field/field.multilingual.inc
@@ -7,6 +7,7 @@
 
 use Drupal\Core\Language\Language;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\field\FieldInterface;
 
 /**
  * @defgroup field_language Field Language API
@@ -124,13 +125,13 @@ function field_language_fallback(&$field_langcodes, EntityInterface $entity, $la
  * @return
  *   An array of valid language codes.
  */
-function field_available_languages($entity_type, $field) {
+function field_available_languages($entity_type, FieldInterface $field) {
   static $drupal_static_fast;
   if (!isset($drupal_static_fast)) {
     $drupal_static_fast['field_langcodes'] = &drupal_static(__FUNCTION__);
   }
   $field_langcodes = &$drupal_static_fast['field_langcodes'];
-  $field_name = $field['field_name'];
+  $field_name = $field->getFieldName();
 
   if (!isset($field_langcodes[$entity_type][$field_name])) {
     // If the field has language support enabled we retrieve an (alterable) list
@@ -215,8 +216,8 @@ function field_language_fallback_enabled() {
  * @return
  *   TRUE if the field can be translated.
  */
-function field_is_translatable($entity_type, $field) {
-  return $field['translatable'] && field_has_translation_handler($entity_type);
+function field_is_translatable($entity_type, FieldInterface $field) {
+  return $field->isFieldTranslatable() && field_has_translation_handler($entity_type);
 }
 
 /**
@@ -309,17 +310,17 @@ function field_language(EntityInterface $entity, $field_name = NULL, $langcode =
     // if the field translation is not available. It is up to translation
     // handlers to implement language fallback rules.
     foreach (field_info_instances($entity_type, $bundle) as $instance) {
-      if (isset($entity->{$instance['field_name']}[$langcode])) {
-        $display_langcode[$instance['field_name']] = $langcode;
+      if (isset($entity->{$instance->getFieldName()}[$langcode])) {
+        $display_langcode[$instance->getFieldName()] = $langcode;
       }
       else {
         // If the field has a value for one of the locked languages, then use
         // that language for display. If not, the default one will be
         // Language::LANGCODE_NOT_SPECIFIED.
-        $display_langcode[$instance['field_name']] = Language::LANGCODE_NOT_SPECIFIED;
+        $display_langcode[$instance->getFieldName()] = Language::LANGCODE_NOT_SPECIFIED;
         foreach (language_list(Language::STATE_LOCKED) as $language_locked) {
-          if (isset($entity->{$instance['field_name']}[$language_locked->id])) {
-            $display_langcode[$instance['field_name']] = $language_locked->id;
+          if (isset($entity->{$instance->getFieldName()}[$language_locked->id])) {
+            $display_langcode[$instance->getFieldName()] = $language_locked->id;
             break;
           }
         }
diff --git a/core/modules/field/field.purge.inc b/core/modules/field/field.purge.inc
index e280187..29aabd8 100644
--- a/core/modules/field/field.purge.inc
+++ b/core/modules/field/field.purge.inc
@@ -98,7 +98,7 @@ function field_purge_batch($batch_size) {
   $factory = Drupal::service('entity.query');
   $info = entity_get_info();
   foreach ($instances as $instance) {
-    $entity_type = $instance['entity_type'];
+    $entity_type = $instance->entity_type;
 
     // EntityFieldQuery currently fails on conditions on comment bundle.
     // Remove when http://drupal.org/node/731724 is fixed.
@@ -108,13 +108,13 @@ function field_purge_batch($batch_size) {
 
     $ids = (object) array(
       'entity_type' => $entity_type,
-      'bundle' => $instance['bundle'],
+      'bundle' => $instance->bundle,
     );
     // field_purge_data() will need the field array.
-    $field = field_info_field_by_id($instance['field_id']);
+    $field = field_info_field_by_id($instance->getField()->uuid);
     // Retrieve some entities.
     $query = $factory->get($entity_type)
-      ->condition('id:' . $field['uuid'] . '.deleted', 1)
+      ->condition('id:' . $field->uuid . '.deleted', 1)
       ->range(0, $batch_size);
     // If there's no bundle key, all results will have the same bundle.
     if (!empty($info[$entity_type]['entity_keys']['bundle'])) {
@@ -148,7 +148,7 @@ function field_purge_batch($batch_size) {
   $deleted_fields = Drupal::state()->get('field.field.deleted') ?: array();
   foreach ($deleted_fields as $field) {
     $field = new Field($field);
-    $instances = field_read_instances(array('field_id' => $field['uuid']), array('include_deleted' => 1));
+    $instances = field_read_instances(array('field_id' => $field->uuid), array('include_deleted' => 1));
     if (empty($instances)) {
       field_purge_field($field);
     }
@@ -177,7 +177,7 @@ function field_purge_data(EntityInterface $entity, $field, $instance) {
   }
 
   // Tell the field storage system to purge the data.
-  module_invoke($field['storage']['module'], 'field_storage_purge', $entity, $field, $instance);
+  module_invoke($field->storage['module'], 'field_storage_purge', $entity, $field, $instance);
 
   // Let other modules act on purging the data.
   foreach (Drupal::moduleHandler()->getImplementations('field_attach_purge') as $module) {
@@ -197,12 +197,12 @@ function field_purge_data(EntityInterface $entity, $field, $instance) {
  */
 function field_purge_instance($instance) {
   // Notify the storage engine.
-  $field = field_info_field_by_id($instance['field_id']);
-  module_invoke($field['storage']['module'], 'field_storage_purge_instance', $instance);
+  $field = field_info_field_by_id($instance->getField()->uuid);
+  module_invoke($field->storage['module'], 'field_storage_purge_instance', $instance);
 
   $state = Drupal::state();
   $deleted_instances = $state->get('field.instance.deleted');
-  unset($deleted_instances[$instance['uuid']]);
+  unset($deleted_instances[$instance->uuid]);
   $state->set('field.instance.deleted', $deleted_instances);
 
   // Clear the cache.
@@ -222,18 +222,18 @@ function field_purge_instance($instance) {
  *   The field record to purge.
  */
 function field_purge_field($field) {
-  $instances = field_read_instances(array('field_id' => $field['uuid']), array('include_deleted' => 1));
+  $instances = field_read_instances(array('field_id' => $field->uuid), array('include_deleted' => 1));
   if (count($instances) > 0) {
-    throw new FieldException(t('Attempt to purge a field @field_name that still has instances.', array('@field_name' => $field['field_name'])));
+    throw new FieldException(t('Attempt to purge a field @field_name that still has instances.', array('@field_name' => $field->getFieldName())));
   }
 
   $state = Drupal::state();
   $deleted_fields = $state->get('field.field.deleted');
-  unset($deleted_fields[$field['uuid']]);
+  unset($deleted_fields[$field->uuid]);
   $state->set('field.field.deleted', $deleted_fields);
 
   // Notify the storage engine.
-  module_invoke($field['storage']['module'], 'field_storage_purge_field', $field);
+  module_invoke($field->storage['module'], 'field_storage_purge_field', $field);
 
   // Clear the cache.
   field_info_cache_clear();
diff --git a/core/modules/field/field.views.inc b/core/modules/field/field.views.inc
index e5dea3b..ad2fa5a 100644
--- a/core/modules/field/field.views.inc
+++ b/core/modules/field/field.views.inc
@@ -8,6 +8,7 @@
  */
 
 use Drupal\Component\Utility\NestedArray;
+use Drupal\field\FieldInterface;
 
 /**
  * Implements hook_views_data().
@@ -18,11 +19,11 @@
 function field_views_data() {
   $data = array();
   foreach (field_info_fields() as $field) {
-    if ($field['storage']['type'] != 'field_sql_storage') {
+    if ($field->storage['type'] != 'field_sql_storage') {
       continue;
     }
 
-    $module = $field['module'];
+    $module = $field->module;
     $result = (array) module_invoke($module, 'field_views_data', $field);
 
     if (empty($result)) {
@@ -48,11 +49,11 @@ function field_views_data() {
  */
 function field_views_data_alter(&$data) {
   foreach (field_info_fields() as $field) {
-    if ($field['storage']['type'] != 'field_sql_storage') {
+    if ($field->storage['type'] != 'field_sql_storage') {
       continue;
     }
 
-    $function = $field['module'] . '_field_views_data_views_data_alter';
+    $function = $field->module . '_field_views_data_views_data_alter';
     if (function_exists($function)) {
       $function($data, $field);
     }
@@ -72,8 +73,8 @@ function field_views_field_label($field_name) {
   foreach ($instances as $entity_name => $entity_type) {
     foreach ($entity_type as $bundle) {
       if (isset($bundle[$field_name])) {
-        $label_counter[$bundle[$field_name]['label']] = isset($label_counter[$bundle[$field_name]['label']]) ? ++$label_counter[$bundle[$field_name]->label] : 1;
-        $all_labels[$entity_name][$bundle[$field_name]['label']] = TRUE;
+        $label_counter[$bundle[$field_name]->getFieldLabel()] = isset($label_counter[$bundle[$field_name]->getFieldLabel()]) ? ++$label_counter[$bundle[$field_name]->getFieldLabel()] : 1;
+        $all_labels[$entity_name][$bundle[$field_name]->getFieldLabel()] = TRUE;
       }
     }
   }
@@ -93,7 +94,7 @@ function field_views_field_default_views_data($field) {
   $field_types = \Drupal::service('plugin.manager.entity.field.field_type')->getDefinitions();
 
   // Check the field module is available.
-  if (!isset($field_types[$field['type']])) {
+  if (!isset($field_types[$field->getFieldType()])) {
     return;
   }
 
@@ -110,10 +111,10 @@ function field_views_field_default_views_data($field) {
   $revision_tables = array();
   $groups = array();
 
-  $group_name = count($field['bundles']) > 1 ? t('Field') : NULL;
+  $group_name = count($field->getBundles()) > 1 ? t('Field') : NULL;
 
   // Build the relationships between the field table and the entity tables.
-  foreach ($field['bundles'] as $entity => $bundles) {
+  foreach ($field->getBundles() as $entity => $bundles) {
     $entity_info = entity_get_info($entity);
     $groups[$entity] = $entity_info['label'];
 
@@ -171,25 +172,25 @@ function field_views_field_default_views_data($field) {
   }
 
   $add_fields = array('delta', 'langcode', 'bundle');
-  foreach ($field['columns'] as $column_name => $attributes) {
-    $add_fields[] = _field_sql_storage_columnname($field['field_name'], $column_name);
+  foreach ($field->getColumns() as $column_name => $attributes) {
+    $add_fields[] = _field_sql_storage_columnname($field->getFieldName(), $column_name);
   }
 
   // Note: we don't have a label available here, because we are at the field
   // level, not at the instance level. So we just go through all instances
   // and take the one which is used the most frequently.
-  $field_name = $field['field_name'];
+  $field_name = $field->getFieldName();
   list($label, $all_labels) = field_views_field_label($field_name);
   foreach ($tables as $type => $table) {
     if ($type == FIELD_LOAD_CURRENT) {
       $group = $group_name;
       $old_column = 'entity_id';
-      $column = $field['field_name'];
+      $column = $field->getFieldName();
     }
     else {
       $group = t('@group (historical data)', array('@group' => $group_name));
       $old_column = 'revision_id';
-      $column = $field['field_name'] . '-' . $old_column;
+      $column = $field->getFieldName() . '-' . $old_column;
     }
 
     $data[$table][$column] = array(
@@ -237,12 +238,12 @@ function field_views_field_default_views_data($field) {
       $data[$table][$column]['help'] .= ' ' . t('Also known as: !also.', array('!also' => implode(', ', $also_known)));
     }
 
-    $keys = array_keys($field['columns']);
+    $keys = array_keys($field->getColumns());
     $real_field = reset($keys);
     $data[$table][$column]['field'] = array(
       'table' => $table,
       'id' => 'field',
-      'field_name' => $field['field_name'],
+      'field_name' => $field->getFieldName(),
       // Provide a real field for group by.
       'real field' => $column . '_' . $real_field,
       'additional fields' => $add_fields,
@@ -253,7 +254,7 @@ function field_views_field_default_views_data($field) {
     );
   }
 
-  foreach ($field['columns'] as $column => $attributes) {
+  foreach ($field->getColumns() as $column => $attributes) {
     $allow_sort = TRUE;
 
     // Identify likely filters and arguments for each column based on field type.
@@ -280,12 +281,12 @@ function field_views_field_default_views_data($field) {
         break;
     }
 
-    if (count($field['columns']) == 1 || $column == 'value') {
-      $title = t('@label (!name)', array('@label' => $label, '!name' => $field['field_name']));
+    if (count($field->getColumns()) == 1 || $column == 'value') {
+      $title = t('@label (!name)', array('@label' => $label, '!name' => $field->getFieldName()));
       $title_short = $label;
     }
     else {
-      $title = t('@label (!name:!column)', array('@label' => $label, '!name' => $field['field_name'], '!column' => $column));
+      $title = t('@label (!name:!column)', array('@label' => $label, '!name' => $field->getFieldName(), '!column' => $column));
       $title_short = t('@label:!column', array('@label' => $label, '!column' => $column));
     }
 
@@ -296,10 +297,11 @@ function field_views_field_default_views_data($field) {
       else {
         $group = t('@group (historical data)', array('@group' => $group_name));
       }
-      $column_real_name = $field['storage_details']['sql'][$type][$table][$column];
+      $storage_details = $field->getStorageDetails();
+      $column_real_name = $storage_details['sql'][$type][$table][$column];
 
       // Load all the fields from the table by default.
-      $additional_fields = array_values($field['storage_details']['sql'][$type][$table]);
+      $additional_fields = array_values($storage_details['sql'][$type][$table]);
 
       $data[$table][$column_real_name] = array(
         'group' => $group,
@@ -315,11 +317,11 @@ function field_views_field_default_views_data($field) {
       foreach ($all_labels as $entity_name => $labels) {
         foreach ($labels as $label_name => $true) {
           if ($group_name != $groups[$entity_name] || $label != $label_name) {
-            if (count($field['columns']) == 1 || $column == 'value') {
-              $alias_title = t('@label (!name)', array('@label' => $label_name, '!name' => $field['field_name']));
+            if (count($field->getColumns()) == 1 || $column == 'value') {
+              $alias_title = t('@label (!name)', array('@label' => $label_name, '!name' => $field->getFieldName()));
             }
             else {
-              $alias_title = t('@label (!name:!column)', array('@label' => $label_name, '!name' => $field['field_name'], '!column' => $column));
+              $alias_title = t('@label (!name:!column)', array('@label' => $label_name, '!name' => $field->getFieldName(), '!column' => $column));
             }
             $aliases[] = array(
               'group' => $groups[$entity_name],
@@ -340,7 +342,7 @@ function field_views_field_default_views_data($field) {
         'table' => $table,
         'id' => $argument,
         'additional fields' => $additional_fields,
-        'field_name' => $field['field_name'],
+        'field_name' => $field->getFieldName(),
         'empty field name' => t('- No value -'),
       );
       $data[$table][$column_real_name]['filter'] = array(
@@ -348,7 +350,7 @@ function field_views_field_default_views_data($field) {
         'table' => $table,
         'id' => $filter,
         'additional fields' => $additional_fields,
-        'field_name' => $field['field_name'],
+        'field_name' => $field->getFieldName(),
         'allow empty' => TRUE,
       );
       if (!empty($allow_sort)) {
@@ -357,13 +359,13 @@ function field_views_field_default_views_data($field) {
           'table' => $table,
           'id' => $sort,
           'additional fields' => $additional_fields,
-          'field_name' => $field['field_name'],
+          'field_name' => $field->getFieldName(),
         );
       }
 
       // Expose additional delta column for multiple value fields.
-      if ($field['cardinality'] > 1 || $field['cardinality'] == FIELD_CARDINALITY_UNLIMITED) {
-        $title_delta = t('@label (!name:delta)', array('@label' => $label, '!name' => $field['field_name']));
+      if ($field->getFieldCardinality() > 1 || $field->getFieldCardinality() == FIELD_CARDINALITY_UNLIMITED) {
+        $title_delta = t('@label (!name:delta)', array('@label' => $label, '!name' => $field->getFieldName()));
         $title_short_delta = t('@label:delta', array('@label' => $label));
 
         $data[$table]['delta'] = array(
@@ -381,14 +383,14 @@ function field_views_field_default_views_data($field) {
           'id' => 'numeric',
           'additional fields' => $additional_fields,
           'empty field name' => t('- No value -'),
-          'field_name' => $field['field_name'],
+          'field_name' => $field->getFieldName(),
         );
         $data[$table]['delta']['filter'] = array(
           'field' => 'delta',
           'table' => $table,
           'id' => 'numeric',
           'additional fields' => $additional_fields,
-          'field_name' => $field['field_name'],
+          'field_name' => $field->getFieldName(),
           'allow empty' => TRUE,
         );
         $data[$table]['delta']['sort'] = array(
@@ -396,13 +398,13 @@ function field_views_field_default_views_data($field) {
           'table' => $table,
           'id' => 'standard',
           'additional fields' => $additional_fields,
-          'field_name' => $field['field_name'],
+          'field_name' => $field->getFieldName(),
         );
       }
 
       // Expose additional language column for translatable fields.
-      if (!empty($field['translatable'])) {
-        $title_language = t('@label (!name:language)', array('@label' => $label, '!name' => $field['field_name']));
+      if ($field->isFieldTranslatable()) {
+        $title_language = t('@label (!name:language)', array('@label' => $label, '!name' => $field->getFieldName()));
         $title_short_language = t('@label:language', array('@label' => $label));
 
         $data[$table]['language'] = array(
@@ -420,14 +422,14 @@ function field_views_field_default_views_data($field) {
           'id' => 'language',
           'additional fields' => $additional_fields,
           'empty field name' => t('- No value -'),
-          'field_name' => $field['field_name'],
+          'field_name' => $field->getFieldName(),
         );
         $data[$table]['language']['filter'] = array(
           'field' => 'language',
           'table' => $table,
           'id' => 'language',
           'additional fields' => $additional_fields,
-          'field_name' => $field['field_name'],
+          'field_name' => $field->getFieldName(),
           'allow empty' => TRUE,
         );
         $data[$table]['language']['sort'] = array(
@@ -435,7 +437,7 @@ function field_views_field_default_views_data($field) {
           'table' => $table,
           'id' => 'standard',
           'additional fields' => $additional_fields,
-          'field_name' => $field['field_name'],
+          'field_name' => $field->getFieldName(),
         );
       }
     }
@@ -447,7 +449,7 @@ function field_views_field_default_views_data($field) {
 /**
  * Have a different filter handler for lists. This should allow to select values of the list.
  */
-function list_field_views_data($field) {
+function list_field_views_data(FieldInterface $field) {
   $data = field_views_field_default_views_data($field);
   foreach ($data as $table_name => $table_data) {
     foreach ($table_data as $field_name => $field_data) {
diff --git a/core/modules/field/lib/Drupal/field/Entity/Field.php b/core/modules/field/lib/Drupal/field/Entity/Field.php
index 3d9f6a1..f687f3b 100644
--- a/core/modules/field/lib/Drupal/field/Entity/Field.php
+++ b/core/modules/field/lib/Drupal/field/Entity/Field.php
@@ -488,7 +488,7 @@ public function delete() {
   /**
    * {@inheritdoc}
    */
-  public function getSchema() {
+  public function getSchema($key = '') {
     if (!isset($this->schema)) {
       // Get the schema from the field item class.
       $definition = \Drupal::service('plugin.manager.entity.field.field_type')->getDefinition($this->type);
@@ -509,6 +509,10 @@ public function getSchema() {
       $this->schema = $schema;
     }
 
+    if (!empty($key)) {
+      return $this->schema[$key];
+    }
+
     return $this->schema;
   }
 
@@ -548,10 +552,15 @@ public function getStorageDetails() {
   /**
    * {@inheritdoc}
    */
-  public function getBundles() {
+  public function getBundles($entity_type = '') {
     if (empty($this->deleted)) {
       $map = field_info_field_map();
-      if (isset($map[$this->id]['bundles'])) {
+      if (!empty($entity_type)) {
+        if (isset($map[$this->id]['bundles'][$entity_type])) {
+          return $map[$this->id]['bundles'][$entity_type];
+        }
+      }
+      elseif (isset($map[$this->id]['bundles'])) {
         return $map[$this->id]['bundles'];
       }
     }
@@ -655,62 +664,6 @@ public function isFieldRequired() {
   public function getFieldDefaultValue(EntityInterface $entity) { }
 
   /**
-   * {@inheritdoc}
-   */
-  public function offsetExists($offset) {
-    return isset($this->{$offset}) || in_array($offset, array('columns', 'foreign keys', 'bundles', 'storage_details'));
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function &offsetGet($offset) {
-    switch ($offset) {
-      case 'id':
-        return $this->uuid;
-
-      case 'field_name':
-        return $this->id;
-
-      case 'columns':
-        $this->getSchema();
-        return $this->schema['columns'];
-
-      case 'foreign keys':
-        $this->getSchema();
-        return $this->schema['foreign keys'];
-
-      case 'bundles':
-        $bundles = $this->getBundles();
-        return $bundles;
-
-      case 'storage_details':
-        $this->getStorageDetails();
-        return $this->storageDetails;
-    }
-
-    return $this->{$offset};
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function offsetSet($offset, $value) {
-    if (!in_array($offset, array('columns', 'foreign keys', 'bundles', 'storage_details'))) {
-      $this->{$offset} = $value;
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function offsetUnset($offset) {
-    if (!in_array($offset, array('columns', 'foreign keys', 'bundles', 'storage_details'))) {
-      unset($this->{$offset});
-    }
-  }
-
-  /**
    * A list of columns that can not be used as field type columns.
    *
    * @return array
diff --git a/core/modules/field/lib/Drupal/field/Entity/FieldInstance.php b/core/modules/field/lib/Drupal/field/Entity/FieldInstance.php
index c954345..edd8e4c 100644
--- a/core/modules/field/lib/Drupal/field/Entity/FieldInstance.php
+++ b/core/modules/field/lib/Drupal/field/Entity/FieldInstance.php
@@ -585,6 +585,7 @@ public function isFieldRequired() {
     return $this->required;
   }
 
+
   /**
    * {@inheritdoc}
    */
@@ -606,58 +607,6 @@ public function allowBundleRename() {
   }
 
   /**
-   * {@inheritdoc}
-   */
-  public function offsetExists($offset) {
-    return (isset($this->{$offset}) || $offset == 'field_id' || $offset == 'field_name');
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function &offsetGet($offset) {
-    if ($offset == 'field_id') {
-      return $this->field_uuid;
-    }
-    if ($offset == 'field_name') {
-      return $this->field->id;
-    }
-    return $this->{$offset};
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function offsetSet($offset, $value) {
-    if ($offset == 'field_id') {
-      $offset = 'field_uuid';
-    }
-    $this->{$offset} = $value;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function offsetUnset($offset) {
-    if ($offset == 'field_id') {
-      $offset = 'field_uuid';
-    }
-    unset($this->{$offset});
-  }
-
-  /**
-   * Implements the magic __sleep() method.
-   *
-   * Using the Serialize interface and serialize() / unserialize() methods
-   * breaks entity forms in PHP 5.4.
-   * @todo Investigate in https://drupal.org/node/2074253.
-   */
-  public function __sleep() {
-    // Only serialize properties from getExportProperties().
-    return array_keys(array_intersect_key($this->getExportProperties(), get_object_vars($this)));
-  }
-
-  /**
    * Implements the magic __wakeup() method.
    */
   public function __wakeup() {
diff --git a/core/modules/field/lib/Drupal/field/FieldInfo.php b/core/modules/field/lib/Drupal/field/FieldInfo.php
index e97a412..e592de5 100644
--- a/core/modules/field/lib/Drupal/field/FieldInfo.php
+++ b/core/modules/field/lib/Drupal/field/FieldInfo.php
@@ -11,6 +11,8 @@
 use Drupal\Core\Config\ConfigFactory;
 use Drupal\Core\Entity\Field\FieldTypePluginManager;
 use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Field\FieldInterface;
+use Drupal\Field\FieldInstanceInterface;
 
 /**
  * Provides field and instance definitions for the current runtime environment.
@@ -234,7 +236,7 @@ public function getFields() {
     else {
       // Collect and prepare fields.
       foreach (field_read_fields(array(), array('include_deleted' => TRUE)) as $field) {
-        $this->fieldsById[$field['uuid']] = $this->prepareField($field);
+        $this->fieldsById[$field->uuid()] = $this->prepareField($field);
       }
 
       // Store in persistent cache.
@@ -243,8 +245,8 @@ public function getFields() {
 
     // Fill the name/ID map.
     foreach ($this->fieldsById as $field) {
-      if (!$field['deleted']) {
-        $this->fieldIdsByName[$field['id']] = $field['uuid'];
+      if (!$field->deleted) {
+        $this->fieldIdsByName[$field->getFieldName()] = $field->uuid();
       }
     }
 
@@ -280,9 +282,9 @@ public function getInstances($entity_type = NULL) {
         $this->getFields();
 
         foreach (field_read_instances() as $instance) {
-          $field = $this->getField($instance['field_name']);
-          $instance = $this->prepareInstance($instance, $field['type']);
-          $this->bundleInstances[$instance['entity_type']][$instance['bundle']][$instance['field_name']] = $instance;
+          $field = $this->getField($instance->getFieldName());
+          $instance = $this->prepareInstance($instance, $field->getFieldType());
+          $this->bundleInstances[$instance->entity_type][$instance->bundle][$instance->getFieldName()] = $instance;
         }
 
         // Store in persistent cache.
@@ -328,8 +330,8 @@ public function getField($field_name) {
       $field = $this->prepareField($field);
 
       // Save in the "static" cache.
-      $this->fieldsById[$field['uuid']] = $field;
-      $this->fieldIdsByName[$field['field_name']] = $field['uuid'];
+      $this->fieldsById[$field->uuid()] = $field;
+      $this->fieldIdsByName[$field->getFieldName()] = $field->uuid();
 
       return $field;
     }
@@ -367,9 +369,9 @@ public function getFieldById($field_id) {
       $field = $this->prepareField($field);
 
       // Store in the static cache.
-      $this->fieldsById[$field['uuid']] = $field;
-      if (!$field['deleted']) {
-        $this->fieldIdsByName[$field['field_name']] = $field['uuid'];
+      $this->fieldsById[$field->uuid()] = $field;
+      if (!$field->deleted) {
+        $this->fieldIdsByName[$field->getFieldName()] = $field->uuid();
       }
 
       return $field;
@@ -410,10 +412,10 @@ public function getBundleInstances($entity_type, $bundle) {
 
       // Extract the field definitions and save them in the "static" cache.
       foreach ($fields as $field) {
-        if (!isset($this->fieldsById[$field['uuid']])) {
-          $this->fieldsById[$field['uuid']] = $field;
-          if (!$field['deleted']) {
-            $this->fieldIdsByName[$field['field_name']] = $field['uuid'];
+        if (!isset($this->fieldsById[$field->uuid()])) {
+          $this->fieldsById[$field->uuid()] = $field;
+          if (!$field->deleted) {
+            $this->fieldIdsByName[$field->getFieldName()] = $field->uuid();
           }
         }
       }
@@ -457,20 +459,20 @@ public function getBundleInstances($entity_type, $bundle) {
         $loaded_instances = entity_load_multiple('field_instance', array_values($config_ids));
 
         foreach ($loaded_instances as $instance) {
-          $field = $loaded_fields[$instance['field_name']];
+          $field = $loaded_fields[$instance->getFieldName()];
 
-          $instance = $this->prepareInstance($instance, $field['type']);
-          $instances[$field['field_name']] = $instance;
+          $instance = $this->prepareInstance($instance, $field->getFieldType());
+          $instances[$field->getFieldName()] = $instance;
 
           // If the field is not in our global "static" list yet, add it.
-          if (!isset($this->fieldsById[$field['uuid']])) {
+          if (!isset($this->fieldsById[$field->uuid()])) {
             $field = $this->prepareField($field);
 
-            $this->fieldsById[$field['uuid']] = $field;
-            $this->fieldIdsByName[$field['field_name']] = $field['uuid'];
+            $this->fieldsById[$field->uuid()] = $field;
+            $this->fieldIdsByName[$field->getFieldName()] = $field->uuid();
           }
 
-          $fields[] = $this->fieldsById[$field['uuid']];
+          $fields[] = $this->fieldsById[$field->uuid()];
         }
       }
     }
@@ -564,10 +566,10 @@ public function getBundleExtraFields($entity_type, $bundle) {
    * @return
    *   The field definition completed for the current runtime context.
    */
-  public function prepareField($field) {
+  public function prepareField(FieldInterface $field) {
     // Make sure all expected field settings are present.
-    $field['settings'] += $this->fieldTypeManager->getDefaultSettings($field['type']);
-    $field['storage']['settings'] += field_info_storage_settings($field['storage']['type']);
+    $field->settings += $this->fieldTypeManager->getDefaultSettings($field->getFieldType());
+    $field->storage['settings'] += field_info_storage_settings($field->storage['type']);
 
     return $field;
   }
@@ -583,13 +585,13 @@ public function prepareField($field) {
    * @return
    *   The field instance array completed for the current runtime context.
    */
-  public function prepareInstance($instance, $field_type) {
+  public function prepareInstance(FieldInstanceInterface $instance, $field_type) {
     // Make sure all expected instance settings are present.
-    $instance['settings'] += $this->fieldTypeManager->getDefaultInstanceSettings($field_type);
+    $instance->settings += $this->fieldTypeManager->getDefaultInstanceSettings($field_type);
 
     // Set a default value for the instance.
-    if (field_behaviors_widget('default value', $instance) == FIELD_BEHAVIOR_DEFAULT && !isset($instance['default_value'])) {
-      $instance['default_value'] = NULL;
+    if (field_behaviors_widget('default value', $instance) == FIELD_BEHAVIOR_DEFAULT && !isset($instance->default_value)) {
+      $instance->default_value = NULL;
     }
 
     return $instance;
diff --git a/core/modules/field/lib/Drupal/field/FieldInstanceInterface.php b/core/modules/field/lib/Drupal/field/FieldInstanceInterface.php
index 318bf4f..d9da54c 100644
--- a/core/modules/field/lib/Drupal/field/FieldInstanceInterface.php
+++ b/core/modules/field/lib/Drupal/field/FieldInstanceInterface.php
@@ -13,7 +13,7 @@
 /**
  * Provides an interface defining a field instance entity.
  */
-interface FieldInstanceInterface extends ConfigEntityInterface, FieldDefinitionInterface, \ArrayAccess {
+interface FieldInstanceInterface extends ConfigEntityInterface, FieldDefinitionInterface {
 
   /**
    * Returns the field entity for this instance.
@@ -24,6 +24,14 @@
   public function getField();
 
   /**
+   * Returns the field type from the field for this instance.
+   *
+   * @return $type
+   *   The field type.
+   */
+  public function getFieldType();
+
+  /**
    * Allows a bundle to be renamed.
    *
    * Renaming a bundle on the instance is allowed when an entity's bundle
diff --git a/core/modules/field/lib/Drupal/field/FieldInterface.php b/core/modules/field/lib/Drupal/field/FieldInterface.php
index 831f295..fce391c 100644
--- a/core/modules/field/lib/Drupal/field/FieldInterface.php
+++ b/core/modules/field/lib/Drupal/field/FieldInterface.php
@@ -13,11 +13,14 @@
 /**
  * Provides an interface defining a field entity.
  */
-interface FieldInterface extends ConfigEntityInterface, FieldDefinitionInterface, \ArrayAccess {
+interface FieldInterface extends ConfigEntityInterface, FieldDefinitionInterface {
 
   /**
    * Returns the field schema.
    *
+   * @param string $key
+   *   (optional) A key corresponding to one of the keys in the schema array.
+   *
    * @return array
    *   The field schema, as an array of key/value pairs in the format returned
    *   by hook_field_schema():
@@ -31,7 +34,7 @@
    *     however, that depending on the storage backend specified for the field,
    *     the field data is not necessarily stored in SQL.
    */
-  public function getSchema();
+  public function getSchema($key = '');
 
   /**
    * Returns the field columns, as defined in the field schema.
@@ -75,10 +78,13 @@ public function getStorageDetails();
   /**
    * Returns the list of bundles where the field has instances.
    *
+   * @param string $entity_type
+   *   (optional) The name of the entity type to look for.
+   *
    * @return array
    *   An array keyed by entity type names, whose values are arrays of bundle
    *   names.
    */
-  public function getBundles();
+  public function getBundles($entity_type = '');
 
 }
diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetBase.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetBase.php
index 4cf4556..1a54f32 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetBase.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetBase.php
@@ -48,7 +48,6 @@
    */
   public function __construct($plugin_id, array $plugin_definition, FieldDefinitionInterface $field_definition, array $settings) {
     parent::__construct(array(), $plugin_id, $plugin_definition);
-
     $this->fieldDefinition = $field_definition;
     $this->settings = $settings;
   }
diff --git a/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php b/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php
index a487a7a..7124161 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php
@@ -115,7 +115,7 @@ public function init(ViewExecutable $view, DisplayPluginBase $display, array &$o
     $this->multiple = FALSE;
     $this->limit_values = FALSE;
 
-    if ($field['cardinality'] > 1 || $field['cardinality'] == FIELD_CARDINALITY_UNLIMITED) {
+    if ($field->getFieldCardinality() > 1 || $field->getFieldCardinality() == FIELD_CARDINALITY_UNLIMITED) {
       $this->multiple = TRUE;
 
       // If "Display all values in the same row" is FALSE, then we always limit
@@ -131,7 +131,7 @@ public function init(ViewExecutable $view, DisplayPluginBase $display, array &$o
 
       // Otherwise, we only limit values if the user hasn't selected "all", 0, or
       // the value matching field cardinality.
-      if ((intval($this->options['delta_limit']) && ($this->options['delta_limit'] != $field['cardinality'])) || intval($this->options['delta_offset'])) {
+      if ((intval($this->options['delta_limit']) && ($this->options['delta_limit'] != $field->getFieldCardinality())) || intval($this->options['delta_offset'])) {
         $this->limit_values = TRUE;
       }
     }
@@ -299,8 +299,8 @@ protected function defineOptions() {
 
     // defineOptions runs before init/construct, so no $this->field_info
     $field = field_info_field($this->definition['field_name']);
-    $field_type = \Drupal::service('plugin.manager.entity.field.field_type')->getDefinition($field['type']);
-    $column_names = array_keys($field['columns']);
+    $field_type = \Drupal::service('plugin.manager.entity.field.field_type')->getDefinition($field->getFieldType());
+    $column_names = array_keys($field->getColumns());
     $default_column = '';
     // Try to determine a sensible default.
     if (count($column_names) == 1) {
@@ -335,7 +335,7 @@ protected function defineOptions() {
     // If we know the exact number of allowed values, then that can be
     // the default. Otherwise, default to 'all'.
     $options['delta_limit'] = array(
-      'default' => ($field['cardinality'] > 1) ? $field['cardinality'] : 'all',
+      'default' => ($field->getFieldCardinality() > 1) ? $field->getFieldCardinality() : 'all',
     );
     $options['delta_offset'] = array(
       'default' => 0,
@@ -371,8 +371,8 @@ public function buildOptionsForm(&$form, &$form_state) {
     parent::buildOptionsForm($form, $form_state);
 
     $field = $this->field_info;
-    $formatters = $this->formatterPluginManager->getOptions($field['type']);
-    $column_names = array_keys($field['columns']);
+    $formatters = $this->formatterPluginManager->getOptions($field->getFieldType());
+    $column_names = array_keys($field->getColumns());
 
     // If this is a multiple value field, add its options.
     if ($this->multiple) {
@@ -380,7 +380,7 @@ public function buildOptionsForm(&$form, &$form_state) {
     }
 
     // No need to ask the user anything if the field has only one column.
-    if (count($field['columns']) == 1) {
+    if (count($field->getColumns()) == 1) {
       $form['click_sort_column'] = array(
         '#type' => 'value',
         '#value' => isset($column_names[0]) ? $column_names[0] : '',
@@ -470,14 +470,14 @@ function multiple_options_form(&$form, &$form_state) {
     // translating prefix and suffix separately.
     list($prefix, $suffix) = explode('@count', t('Display @count value(s)'));
 
-    if ($field['cardinality'] == FIELD_CARDINALITY_UNLIMITED) {
+    if ($field->getFieldCardinality() == FIELD_CARDINALITY_UNLIMITED) {
       $type = 'textfield';
       $options = NULL;
       $size = 5;
     }
     else {
       $type = 'select';
-      $options = drupal_map_assoc(range(1, $field['cardinality']));
+      $options = drupal_map_assoc(range(1, $field->getFieldCardinality()));
       $size = 1;
     }
     $form['multi_type'] = array(
@@ -577,7 +577,7 @@ public function buildGroupByForm(&$form, &$form_state) {
     // and any additional grouping columns must be specified.
     $group_columns = array(
       'entity_id' => t('Entity ID'),
-    ) + drupal_map_assoc(array_keys($this->field_info['columns']), 'ucfirst');
+    ) + drupal_map_assoc(array_keys($this->field_info->getColumns()), 'ucfirst');
 
     $form['group_column'] = array(
       '#type' => 'select',
@@ -798,14 +798,14 @@ function render_item($count, $item) {
 
   protected function documentSelfTokens(&$tokens) {
     $field = $this->field_info;
-    foreach ($field['columns'] as $id => $column) {
+    foreach ($field->getColumns() as $id => $column) {
       $tokens['[' . $this->options['id'] . '-' . $id . ']'] = t('Raw @column', array('@column' => $id));
     }
   }
 
   protected function addSelfTokens(&$tokens, $item) {
     $field = $this->field_info;
-    foreach ($field['columns'] as $id => $column) {
+    foreach ($field->getColumns() as $id => $column) {
       // Use filter_xss_admin because it's user data and we can't be sure it is safe.
       // We know nothing about the data, though, so we can't really do much else.
 
diff --git a/core/modules/field/lib/Drupal/field/Tests/BulkDeleteTest.php b/core/modules/field/lib/Drupal/field/Tests/BulkDeleteTest.php
index 58799f5..8bfff89 100644
--- a/core/modules/field/lib/Drupal/field/Tests/BulkDeleteTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/BulkDeleteTest.php
@@ -142,7 +142,7 @@ function setUp() {
       for ($i = 0; $i < 10; $i++) {
         $entity = entity_create($this->entity_type, array('type' => $bundle));
         foreach ($this->fields as $field) {
-          $entity->{$field['field_name']}->setValue($this->_generateTestFieldValues($field->cardinality));
+          $entity->{$field->getFieldName()}->setValue($this->_generateTestFieldValues($field->getFieldCardinality()));
         }
         $entity->save();
       }
@@ -182,7 +182,7 @@ function testDeleteFieldInstance() {
     $instances = field_read_instances(array('field_id' => $field->uuid, 'deleted' => TRUE), array('include_deleted' => TRUE, 'include_inactive' => TRUE));
     $this->assertEqual(count($instances), 1, 'There is one deleted instance');
     $instance = $instances[0];
-    $this->assertEqual($instance['bundle'], $bundle, 'The deleted instance is for the correct bundle');
+    $this->assertEqual($instance->bundle, $bundle, 'The deleted instance is for the correct bundle');
 
     // There are 0 entities of this bundle with non-deleted data.
     $found = $factory->get('entity_test')
diff --git a/core/modules/field/lib/Drupal/field/Tests/CrudTest.php b/core/modules/field/lib/Drupal/field/Tests/CrudTest.php
index 8e16c3e..e4bbb18 100644
--- a/core/modules/field/lib/Drupal/field/Tests/CrudTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/CrudTest.php
@@ -44,8 +44,8 @@ function testCreateField() {
     $field = entity_create('field_entity', $field_definition);
     $field->save();
     $mem = field_test_memorize();
-    $this->assertIdentical($mem['field_test_field_entity_create'][0][0]['field_name'], $field_definition['field_name'], 'hook_entity_create() called with correct arguments.');
-    $this->assertIdentical($mem['field_test_field_entity_create'][0][0]['type'], $field_definition['type'], 'hook_entity_create() called with correct arguments.');
+    $this->assertIdentical($mem['field_test_field_entity_create'][0][0]->getFieldName(), $field_definition['field_name'], 'hook_entity_create() called with correct arguments.');
+    $this->assertIdentical($mem['field_test_field_entity_create'][0][0]->getFieldType(), $field_definition['type'], 'hook_entity_create() called with correct arguments.');
 
     // Read the configuration. Check against raw configuration data rather than
     // the loaded ConfigEntity, to be sure we check that the defaults are
@@ -311,18 +311,18 @@ function testDeleteField() {
 
     // Test that the first field is not deleted, and then delete it.
     $field = field_read_field($this->field['field_name'], array('include_deleted' => TRUE));
-    $this->assertTrue(!empty($field) && empty($field['deleted']), 'A new field is not marked for deletion.');
+    $this->assertTrue(!empty($field) && empty($field->deleted), 'A new field is not marked for deletion.');
     field_info_field($this->field['field_name'])->delete();
 
     // Make sure that the field is marked as deleted when it is specifically
     // loaded.
     $field = field_read_field($this->field['field_name'], array('include_deleted' => TRUE));
-    $this->assertTrue(!empty($field['deleted']), 'A deleted field is marked for deletion.');
+    $this->assertTrue(!empty($field->deleted), 'A deleted field is marked for deletion.');
 
     // Make sure that this field's instance is marked as deleted when it is
     // specifically loaded.
     $instance = field_read_instance('entity_test', $this->instance_definition['field_name'], $this->instance_definition['bundle'], array('include_deleted' => TRUE));
-    $this->assertTrue(!empty($instance['deleted']), 'An instance for a deleted field is marked for deletion.');
+    $this->assertTrue(!empty($instance->deleted), 'An instance for a deleted field is marked for deletion.');
 
     // Try to load the field normally and make sure it does not show up.
     $field = field_read_field($this->field['field_name']);
@@ -334,32 +334,32 @@ function testDeleteField() {
 
     // Make sure the other field (and its field instance) are not deleted.
     $another_field = field_read_field($this->another_field['field_name']);
-    $this->assertTrue(!empty($another_field) && empty($another_field['deleted']), 'A non-deleted field is not marked for deletion.');
+    $this->assertTrue(!empty($another_field) && empty($another_field->deleted), 'A non-deleted field is not marked for deletion.');
     $another_instance = field_read_instance('entity_test', $another_instance_definition['field_name'], $another_instance_definition['bundle']);
-    $this->assertTrue(!empty($another_instance) && empty($another_instance['deleted']), 'An instance of a non-deleted field is not marked for deletion.');
+    $this->assertTrue(!empty($another_instance) && empty($another_instance->deleted), 'An instance of a non-deleted field is not marked for deletion.');
 
     // Try to create a new field the same name as a deleted field and
     // write data into it.
     entity_create('field_entity', $this->field)->save();
     entity_create('field_instance', $this->instance_definition)->save();
     $field = field_read_field($this->field['field_name']);
-    $this->assertTrue(!empty($field) && empty($field['deleted']), 'A new field with a previously used name is created.');
+    $this->assertTrue(!empty($field) && empty($field->deleted), 'A new field with a previously used name is created.');
     $instance = field_read_instance('entity_test', $this->instance_definition['field_name'], $this->instance_definition['bundle']);
-    $this->assertTrue(!empty($instance) && empty($instance['deleted']), 'A new instance for a previously used field name is created.');
+    $this->assertTrue(!empty($instance) && empty($instance->deleted), 'A new instance for a previously used field name is created.');
 
     // Save an entity with data for the field
     $entity = entity_create('entity_test', array('id' => 0, 'revision_id' => 0));
     $langcode = Language::LANGCODE_NOT_SPECIFIED;
     $values[0]['value'] = mt_rand(1, 127);
-    $entity->{$field['field_name']}->value = $values[0]['value'];
+    $entity->{$field->getFieldName()}->value = $values[0]['value'];
     field_attach_insert($entity);
 
     // Verify the field is present on load
     $entity = entity_create('entity_test', array('id' => 0, 'revision_id' => 0));
     field_attach_load('entity_test', array(0 => $entity));
-    $this->assertIdentical(count($entity->{$field['field_name']}), count($values), "Data in previously deleted field saves and loads correctly");
+    $this->assertIdentical(count($entity->{$field->getFieldName()}), count($values), "Data in previously deleted field saves and loads correctly");
     foreach ($values as $delta => $value) {
-      $this->assertEqual($entity->{$field['field_name']}[$delta]->value, $values[$delta]['value'], "Data in previously deleted field saves and loads correctly");
+      $this->assertEqual($entity->{$field->getFieldName()}[$delta]->value, $values[$delta]['value'], "Data in previously deleted field saves and loads correctly");
     }
   }
 
diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldAccessTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldAccessTest.php
index 0f86ac5..3d87818 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FieldAccessTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FieldAccessTest.php
@@ -51,13 +51,13 @@ function setUp() {
     $content_type_info = $this->drupalCreateContentType();
     $content_type = $content_type_info->type;
 
-    $field = array(
+    $this->field = entity_create('field_entity', array(
       'field_name' => 'test_view_field',
       'type' => 'text',
-    );
-    entity_create('field_entity', $field)->save();
+    ));
+    $this->field->save();
     $instance = array(
-      'field_name' => $field['field_name'],
+      'field_name' => $this->field->id(),
       'entity_type' => 'node',
       'bundle' => $content_type,
     );
@@ -66,7 +66,7 @@ function setUp() {
     // Assign display properties for the 'default' and 'teaser' view modes.
     foreach (array('default', 'teaser') as $view_mode) {
       entity_get_display('node', $content_type, $view_mode)
-        ->setComponent($field['field_name'])
+        ->setComponent($this->field->id())
         ->save();
     }
 
diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldAttachOtherTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldAttachOtherTest.php
index 4739d5f..4c8604f 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FieldAttachOtherTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FieldAttachOtherTest.php
@@ -53,9 +53,9 @@ function testFieldAttachView() {
     $options = array('field_name' => $this->field_name_2);
 
     // Populate values to be displayed.
-    $values = $this->_generateTestFieldValues($this->field['cardinality']);
+    $values = $this->_generateTestFieldValues($this->field->getFieldCardinality());
     $entity_init->{$this->field_name}->setValue($values);
-    $values_2 = $this->_generateTestFieldValues($this->field_2['cardinality']);
+    $values_2 = $this->_generateTestFieldValues($this->field_2->getFieldCardinality());
     $entity_init->{$this->field_name_2}->setValue($values_2);
 
     // Simple formatter, label displayed.
@@ -71,7 +71,7 @@ function testFieldAttachView() {
         'test_formatter_setting' => $formatter_setting,
       ),
     );
-    $display->setComponent($this->field['field_name'], $display_options);
+    $display->setComponent($this->field->getFieldName(), $display_options);
 
     $formatter_setting_2 = $this->randomName();
     $display_options_2 = array(
@@ -81,19 +81,19 @@ function testFieldAttachView() {
         'test_formatter_setting' => $formatter_setting_2,
       ),
     );
-    $display->setComponent($this->field_2['field_name'], $display_options_2);
+    $display->setComponent($this->field_2->getFieldName(), $display_options_2);
 
     // View all fields.
     field_attach_prepare_view($entity_type, array($entity->id() => $entity), $displays);
     $content = field_attach_view($entity, $display);
     $output = drupal_render($content);
     $this->content = $output;
-    $this->assertRaw($this->instance['label'], "First field's label is displayed.");
+    $this->assertRaw($this->instance->label(), "First field's label is displayed.");
     foreach ($values as $delta => $value) {
       $this->content = $output;
       $this->assertRaw("$formatter_setting|{$value['value']}", "Value $delta is displayed, formatter settings are applied.");
     }
-    $this->assertRaw($this->instance_2['label'], "Second field's label is displayed.");
+    $this->assertRaw($this->instance_2->label(), "Second field's label is displayed.");
     foreach ($values_2 as $delta => $value) {
       $this->content = $output;
       $this->assertRaw("$formatter_setting_2|{$value['value']}", "Value $delta is displayed, formatter settings are applied.");
@@ -102,21 +102,21 @@ function testFieldAttachView() {
     // Label hidden.
     $entity = clone($entity_init);
     $display_options['label'] = 'hidden';
-    $display->setComponent($this->field['field_name'], $display_options);
+    $display->setComponent($this->field->id(), $display_options);
     field_attach_prepare_view($entity_type, array($entity->id() => $entity), $displays);
     $entity->content = field_attach_view($entity, $display);
     $output = drupal_render($entity->content);
     $this->content = $output;
-    $this->assertNoRaw($this->instance['label'], "Hidden label: label is not displayed.");
+    $this->assertNoRaw($this->instance->label(), "Hidden label: label is not displayed.");
 
     // Field hidden.
     $entity = clone($entity_init);
-    $display->removeComponent($this->field['field_name']);
+    $display->removeComponent($this->field->getFieldName());
     field_attach_prepare_view($entity_type, array($entity->id() => $entity), $displays);
     $entity->content = field_attach_view($entity, $display);
     $output = drupal_render($entity->content);
     $this->content = $output;
-    $this->assertNoRaw($this->instance['label'], "Hidden field: label is not displayed.");
+    $this->assertNoRaw($this->instance->label(), "Hidden field: label is not displayed.");
     foreach ($values as $delta => $value) {
       $this->assertNoRaw("$formatter_setting|{$value['value']}", "Hidden field: value $delta is not displayed.");
     }
@@ -124,7 +124,7 @@ function testFieldAttachView() {
     // Multiple formatter.
     $entity = clone($entity_init);
     $formatter_setting = $this->randomName();
-    $display->setComponent($this->field['field_name'], array(
+    $display->setComponent($this->field->getFieldName(), array(
       'label' => 'above',
       'type' => 'field_test_multiple',
       'settings' => array(
@@ -144,7 +144,7 @@ function testFieldAttachView() {
     // Test a formatter that uses hook_field_formatter_prepare_view().
     $entity = clone($entity_init);
     $formatter_setting = $this->randomName();
-    $display->setComponent($this->field['field_name'], array(
+    $display->setComponent($this->field->getFieldName(), array(
       'label' => 'above',
       'type' => 'field_test_with_prepare_view',
       'settings' => array(
@@ -184,7 +184,7 @@ function testFieldAttachPrepareViewMultiple() {
 
     // Set the instance to be hidden.
     $display = entity_get_display('entity_test', 'entity_test', 'full')
-      ->removeComponent($this->field['field_name']);
+      ->removeComponent($this->field->getFieldName());
 
     // Set up a second instance on another bundle, with a formatter that uses
     // hook_field_formatter_prepare_view().
@@ -196,7 +196,7 @@ function testFieldAttachPrepareViewMultiple() {
     $this->instance2->save();
 
     $display_2 = entity_get_display('entity_test', 'test_bundle_2', 'full')
-      ->setComponent($this->field['field_name'], array(
+      ->setComponent($this->field->getFieldName(), array(
         'type' => 'field_test_with_prepare_view',
         'settings' => array(
           'test_formatter_setting_additional' => $formatter_setting,
@@ -207,11 +207,11 @@ function testFieldAttachPrepareViewMultiple() {
 
     // Create one entity in each bundle.
     $entity1_init = entity_create('entity_test', array('id' => 1, 'type' => 'entity_test'));
-    $values1 = $this->_generateTestFieldValues($this->field['cardinality']);
+    $values1 = $this->_generateTestFieldValues($this->field->getFieldCardinality());
     $entity1_init->{$this->field_name}->setValue($values1);
 
     $entity2_init = entity_create('entity_test', array('id' => 2, 'type' => 'test_bundle_2'));
-    $values2 = $this->_generateTestFieldValues($this->field['cardinality']);
+    $values2 = $this->_generateTestFieldValues($this->field->getFieldCardinality());
     $entity2_init->{$this->field_name}->setValue($values2);
 
     // Run prepare_view, and check that the entities come out as expected.
@@ -236,9 +236,9 @@ function testFieldAttachPrepareViewMultiple() {
    */
   function testFieldAttachCache() {
     // Initialize random values and a test entity.
-    $entity_init = entity_create('entity_test', array('id' => 1, 'revision_id' => 1, 'type' => $this->instance['bundle']));
+    $entity_init = entity_create('entity_test', array('id' => 1, 'revision_id' => 1, 'type' => $this->instance->bundle));
     $langcode = Language::LANGCODE_NOT_SPECIFIED;
-    $values = $this->_generateTestFieldValues($this->field['cardinality']);
+    $values = $this->_generateTestFieldValues($this->field->getFieldCardinality());
 
     // Non-cacheable entity type.
     $entity_type = 'entity_test';
@@ -298,7 +298,7 @@ function testFieldAttachCache() {
     $this->assertEqual($cache->data[$this->field_name][$langcode], $values, 'Cached: correct cache entry on load');
 
     // Update with different values, and check that the cache entry is wiped.
-    $values = $this->_generateTestFieldValues($this->field['cardinality']);
+    $values = $this->_generateTestFieldValues($this->field->getFieldCardinality());
     $entity = clone($entity_init);
     $entity->{$this->field_name} = $values;
     field_attach_update($entity);
@@ -316,7 +316,7 @@ function testFieldAttachCache() {
       'revision_id' => 2,
       'type' => $entity_type,
     ));
-    $values = $this->_generateTestFieldValues($this->field['cardinality']);
+    $values = $this->_generateTestFieldValues($this->field->getFieldCardinality());
     $entity = clone($entity_init);
     $entity->{$this->field_name} = $values;
     field_attach_update($entity);
@@ -344,22 +344,22 @@ function testFieldAttachForm() {
     $this->createFieldWithInstance('_2');
 
     $entity_type = 'entity_test';
-    $entity = entity_create($entity_type, array('id' => 1, 'revision_id' => 1, 'type' => $this->instance['bundle']));
+    $entity = entity_create($entity_type, array('id' => 1, 'revision_id' => 1, 'type' => $this->instance->bundle));
     $langcode = Language::LANGCODE_NOT_SPECIFIED;
 
     // When generating form for all fields.
     $form = array();
     $form_state = form_state_defaults();
-    $form_state['form_display'] = entity_get_form_display($entity_type, $this->instance['bundle'], 'default');
+    $form_state['form_display'] = entity_get_form_display($entity_type, $this->instance->bundle, 'default');
     field_attach_form($entity, $form, $form_state);
 
-    $this->assertEqual($form[$this->field_name][$langcode]['#title'], $this->instance['label'], "First field's form title is {$this->instance['label']}");
-    $this->assertEqual($form[$this->field_name_2][$langcode]['#title'], $this->instance_2['label'], "Second field's form title is {$this->instance_2['label']}");
-    for ($delta = 0; $delta < $this->field['cardinality']; $delta++) {
+    $this->assertEqual($form[$this->field_name][$langcode]['#title'], $this->instance->label(), "First field's form title is {$this->instance->label()}");
+    $this->assertEqual($form[$this->field_name_2][$langcode]['#title'], $this->instance_2->label(), "Second field's form title is {$this->instance_2->label()}");
+    for ($delta = 0; $delta < $this->field->getFieldCardinality(); $delta++) {
       // field_test_widget uses 'textfield'
       $this->assertEqual($form[$this->field_name][$langcode][$delta]['value']['#type'], 'textfield', "First field's form delta $delta widget is textfield");
     }
-    for ($delta = 0; $delta < $this->field_2['cardinality']; $delta++) {
+    for ($delta = 0; $delta < $this->field_2->getFieldCardinality(); $delta++) {
       // field_test_widget uses 'textfield'
       $this->assertEqual($form[$this->field_name_2][$langcode][$delta]['value']['#type'], 'textfield', "Second field's form delta $delta widget is textfield");
     }
@@ -368,12 +368,12 @@ function testFieldAttachForm() {
     $options = array('field_name' => $this->field_name_2);
     $form = array();
     $form_state = form_state_defaults();
-    $form_state['form_display'] = entity_get_form_display($entity_type, $this->instance['bundle'], 'default');
+    $form_state['form_display'] = entity_get_form_display($entity_type, $this->instance->bundle, 'default');
     field_attach_form($entity, $form, $form_state, NULL, $options);
 
     $this->assertFalse(isset($form[$this->field_name]), 'The first field does not exist in the form');
-    $this->assertEqual($form[$this->field_name_2][$langcode]['#title'], $this->instance_2['label'], "Second field's form title is {$this->instance_2['label']}");
-    for ($delta = 0; $delta < $this->field_2['cardinality']; $delta++) {
+    $this->assertEqual($form[$this->field_name_2][$langcode]['#title'], $this->instance_2->label(), "Second field's form title is {$this->instance_2->label()}");
+    for ($delta = 0; $delta < $this->field_2->getFieldCardinality(); $delta++) {
       // field_test_widget uses 'textfield'
       $this->assertEqual($form[$this->field_name_2][$langcode][$delta]['value']['#type'], 'textfield', "Second field's form delta $delta widget is textfield");
     }
@@ -386,24 +386,24 @@ function testFieldAttachExtractFormValues() {
     $this->createFieldWithInstance('_2');
 
     $entity_type = 'entity_test';
-    $entity_init = entity_create($entity_type, array('id' => 1, 'revision_id' => 1, 'type' => $this->instance['bundle']));
+    $entity_init = entity_create($entity_type, array('id' => 1, 'revision_id' => 1, 'type' => $this->instance->bundle));
     $langcode = Language::LANGCODE_NOT_SPECIFIED;
 
     // Build the form for all fields.
     $form = array();
     $form_state = form_state_defaults();
-    $form_state['form_display'] = entity_get_form_display($entity_type, $this->instance['bundle'], 'default');
+    $form_state['form_display'] = entity_get_form_display($entity_type, $this->instance->bundle, 'default');
     field_attach_form($entity_init, $form, $form_state);
 
     // Simulate incoming values.
     // First field.
     $values = array();
     $weights = array();
-    for ($delta = 0; $delta < $this->field['cardinality']; $delta++) {
+    for ($delta = 0; $delta < $this->field->getFieldCardinality(); $delta++) {
       $values[$delta]['value'] = mt_rand(1, 127);
       // Assign random weight.
       do {
-        $weight = mt_rand(0, $this->field['cardinality']);
+        $weight = mt_rand(0, $this->field->getFieldCardinality());
       } while (in_array($weight, $weights));
       $weights[$delta] = $weight;
       $values[$delta]['_weight'] = $weight;
@@ -413,11 +413,11 @@ function testFieldAttachExtractFormValues() {
     // Second field.
     $values_2 = array();
     $weights_2 = array();
-    for ($delta = 0; $delta < $this->field_2['cardinality']; $delta++) {
+    for ($delta = 0; $delta < $this->field_2->getFieldCardinality(); $delta++) {
       $values_2[$delta]['value'] = mt_rand(1, 127);
       // Assign random weight.
       do {
-        $weight = mt_rand(0, $this->field_2['cardinality']);
+        $weight = mt_rand(0, $this->field_2->getFieldCardinality());
       } while (in_array($weight, $weights_2));
       $weights_2[$delta] = $weight;
       $values_2[$delta]['_weight'] = $weight;
diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldAttachStorageTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldAttachStorageTest.php
index 5d422af..108c765 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FieldAttachStorageTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FieldAttachStorageTest.php
@@ -56,7 +56,7 @@ function testFieldAttachSaveLoad() {
 
     // Configure the instance so that we test hook_field_load() (see
     // field_test_field_load() in field_test.module).
-    $this->instance['settings']['test_hook_field_load'] = TRUE;
+    $this->instance->settings['test_hook_field_load'] = TRUE;
     $this->instance->save();
 
     // TODO : test empty values filtering and "compression" (store consecutive deltas).
@@ -65,7 +65,7 @@ function testFieldAttachSaveLoad() {
     for ($revision_id = 0; $revision_id < 3; $revision_id++) {
       $revision[$revision_id] = entity_create($entity_type, array('id' => 0, 'revision_id' => $revision_id));
       // Note: we try to insert one extra value.
-      $values[$revision_id] = $this->_generateTestFieldValues($this->field['cardinality'] + 1);
+      $values[$revision_id] = $this->_generateTestFieldValues($this->field->getFieldCardinality() + 1);
       $current_revision = $revision_id;
       // If this is the first revision do an insert.
       if (!$revision_id) {
@@ -83,8 +83,8 @@ function testFieldAttachSaveLoad() {
     $entity = entity_create($entity_type, array('id' => 0, 'revision_id' => 0));
     field_attach_load($entity_type, array(0 => $entity));
     // Number of values per field loaded equals the field cardinality.
-    $this->assertEqual(count($entity->{$this->field_name}), $this->field['cardinality'], 'Current revision: expected number of values');
-    for ($delta = 0; $delta < $this->field['cardinality']; $delta++) {
+    $this->assertEqual(count($entity->{$this->field_name}), $this->field->getFieldCardinality(), 'Current revision: expected number of values');
+    for ($delta = 0; $delta < $this->field->getFieldCardinality(); $delta++) {
       // The field value loaded matches the one inserted or updated.
       $this->assertEqual($entity->{$this->field_name}[$delta]->value , $values[$current_revision][$delta]['value'], format_string('Current revision: expected value %delta was found.', array('%delta' => $delta)));
       // The value added in hook_field_load() is found.
@@ -96,8 +96,8 @@ function testFieldAttachSaveLoad() {
       $entity = entity_create($entity_type, array('id' => 0, 'revision_id' => $revision_id));
       field_attach_load_revision($entity_type, array(0 => $entity));
       // Number of values per field loaded equals the field cardinality.
-      $this->assertEqual(count($entity->{$this->field_name}), $this->field['cardinality'], format_string('Revision %revision_id: expected number of values.', array('%revision_id' => $revision_id)));
-      for ($delta = 0; $delta < $this->field['cardinality']; $delta++) {
+      $this->assertEqual(count($entity->{$this->field_name}), $this->field->getFieldCardinality(), format_string('Revision %revision_id: expected number of values.', array('%revision_id' => $revision_id)));
+      for ($delta = 0; $delta < $this->field->getFieldCardinality(); $delta++) {
         // The field value loaded matches the one inserted or updated.
         $this->assertEqual($entity->{$this->field_name}[$delta]->value, $values[$revision_id][$delta]['value'], format_string('Revision %revision_id: expected value %delta was found.', array('%revision_id' => $revision_id, '%delta' => $delta)));
         // The value added in hook_field_load() is found.
@@ -132,7 +132,7 @@ function testFieldAttachLoadMultiple() {
       $field_names[$i] = 'field_' . $i;
       $field = entity_create('field_entity', array('field_name' => $field_names[$i], 'type' => 'test_field'));
       $field->save();
-      $field_ids[$i] = $field['uuid'];
+      $field_ids[$i] = $field->uuid();
       foreach ($field_bundles_map[$i] as $bundle) {
         entity_create('field_instance', array(
           'field_name' => $field_names[$i],
@@ -218,7 +218,7 @@ function testFieldAttachSaveLoadDifferentStorage() {
     $entity = clone($entity_init);
     $values = array();
     foreach ($fields as $field) {
-      $values[$field['field_name']] = $this->_generateTestFieldValues($this->field['cardinality']);
+      $values[$field['field_name']] = $this->_generateTestFieldValues($this->field->getFieldCardinality());
       $entity->{$field['field_name']} = $values[$field['field_name']];
     }
     field_attach_insert($entity);
@@ -253,9 +253,10 @@ function testFieldStorageDetailsAlter() {
     $instance->save();
 
     // The storage details are indexed by a storage engine type.
-    $this->assertTrue(array_key_exists('drupal_variables', $field['storage_details']), 'The storage type is Drupal variables.');
+    $storage_details = $field->getStorageDetails();
+    $this->assertTrue(array_key_exists('drupal_variables', $storage_details), 'The storage type is Drupal variables.');
 
-    $details = $field['storage_details']['drupal_variables'];
+    $details = $storage_details['drupal_variables'];
 
     // The field_test storage details are indexed by variable name. The details
     // are altered, so moon and mars are correct for this test.
@@ -264,7 +265,7 @@ function testFieldStorageDetailsAlter() {
 
     // Test current and revision storage details together because the columns
     // are the same.
-    foreach ($field['columns'] as $column_name => $attributes) {
+    foreach ($field->getColumns() as $column_name => $attributes) {
       $this->assertEqual($details[FIELD_LOAD_CURRENT]['moon'][$column_name], $column_name, format_string('Column name %value matches the definition in %bin.', array('%value' => $column_name, '%bin' => 'moon[FIELD_LOAD_CURRENT]')));
       $this->assertEqual($details[FIELD_LOAD_REVISION]['mars'][$column_name], $column_name, format_string('Column name %value matches the definition in %bin.', array('%value' => $column_name, '%bin' => 'mars[FIELD_LOAD_REVISION]')));
     }
@@ -340,7 +341,7 @@ function testFieldAttachSaveEmptyDataDefaultValue() {
     $this->createFieldWithInstance('', $entity_type);
 
     // Add a default value function.
-    $this->instance['default_value_function'] = 'field_test_default_value';
+    $this->instance->default_value_function = 'field_test_default_value';
     $this->instance->save();
 
     // Verify that fields are populated with default values.
@@ -370,51 +371,51 @@ function testFieldAttachSaveEmptyDataDefaultValue() {
   function testFieldAttachDelete() {
     $entity_type = 'entity_test_rev';
     $this->createFieldWithInstance('', $entity_type);
-    $rev[0] = entity_create($entity_type, array('id' => 0, 'revision_id' => 0, 'type' => $this->instance['bundle']));
+    $rev[0] = entity_create($entity_type, array('id' => 0, 'revision_id' => 0, 'type' => $this->instance->bundle));
 
     // Create revision 0
-    $values = $this->_generateTestFieldValues($this->field['cardinality']);
+    $values = $this->_generateTestFieldValues($this->field->getFieldCardinality());
     $rev[0]->{$this->field_name} = $values;
     field_attach_insert($rev[0]);
 
     // Create revision 1
-    $rev[1] = entity_create($entity_type, array('id' => 0, 'revision_id' => 1, 'type' => $this->instance['bundle']));
+    $rev[1] = entity_create($entity_type, array('id' => 0, 'revision_id' => 1, 'type' => $this->instance->bundle));
     $rev[1]->{$this->field_name} = $values;
     field_attach_update($rev[1]);
 
     // Create revision 2
-    $rev[2] = entity_create($entity_type, array('id' => 0, 'revision_id' => 2, 'type' => $this->instance['bundle']));
+    $rev[2] = entity_create($entity_type, array('id' => 0, 'revision_id' => 2, 'type' => $this->instance->bundle));
     $rev[2]->{$this->field_name} = $values;
     field_attach_update($rev[2]);
 
     // Confirm each revision loads
     foreach (array_keys($rev) as $vid) {
-      $read = entity_create($entity_type, array('id' => 0, 'revision_id' => $vid, 'type' => $this->instance['bundle']));
+      $read = entity_create($entity_type, array('id' => 0, 'revision_id' => $vid, 'type' => $this->instance->bundle));
       field_attach_load_revision($entity_type, array(0 => $read));
-      $this->assertEqual(count($read->{$this->field_name}), $this->field['cardinality'], "The test entity revision $vid has {$this->field['cardinality']} values.");
+      $this->assertEqual(count($read->{$this->field_name}), $this->field->getFieldCardinality(), "The test entity revision $vid has {$this->field->getFieldCardinality()} values.");
     }
 
     // Delete revision 1, confirm the other two still load.
     field_attach_delete_revision($rev[1]);
     foreach (array(0, 2) as $vid) {
-      $read = entity_create($entity_type, array('id' => 0, 'revision_id' => $vid, 'type' => $this->instance['bundle']));
+      $read = entity_create($entity_type, array('id' => 0, 'revision_id' => $vid, 'type' => $this->instance->bundle));
       field_attach_load_revision($entity_type, array(0 => $read));
-      $this->assertEqual(count($read->{$this->field_name}), $this->field['cardinality'], "The test entity revision $vid has {$this->field['cardinality']} values.");
+      $this->assertEqual(count($read->{$this->field_name}), $this->field->getFieldCardinality(), "The test entity revision $vid has {$this->field->getFieldCardinality()} values.");
     }
 
     // Confirm the current revision still loads
-    $read = entity_create($entity_type, array('id' => 0, 'revision_id' => 2, 'type' => $this->instance['bundle']));
+    $read = entity_create($entity_type, array('id' => 0, 'revision_id' => 2, 'type' => $this->instance->bundle));
     field_attach_load($entity_type, array(0 => $read));
-    $this->assertEqual(count($read->{$this->field_name}), $this->field['cardinality'], "The test entity current revision has {$this->field['cardinality']} values.");
+    $this->assertEqual(count($read->{$this->field_name}), $this->field->getFieldCardinality(), "The test entity current revision has {$this->field->getFieldCardinality()} values.");
 
     // Delete all field data, confirm nothing loads
     field_attach_delete($rev[2]);
     foreach (array(0, 1, 2) as $vid) {
-      $read = entity_create($entity_type, array('id' => 0, 'revision_id' => $vid, 'type' => $this->instance['bundle']));
+      $read = entity_create($entity_type, array('id' => 0, 'revision_id' => $vid, 'type' => $this->instance->bundle));
       field_attach_load_revision($entity_type, array(0 => $read));
       $this->assertIdentical($read->{$this->field_name}[0]->getValue(), array(), "The test entity revision $vid is deleted.");
     }
-    $read = entity_create($entity_type, array('id' => 0, 'revision_id' => 2, 'type' => $this->instance['bundle']));
+    $read = entity_create($entity_type, array('id' => 0, 'revision_id' => 2, 'type' => $this->instance->bundle));
     field_attach_load($entity_type, array(0 => $read));
     $this->assertIdentical($read->{$this->field_name}[0]->getValue(), array(), 'The test entity current revision is deleted.');
   }
@@ -435,15 +436,15 @@ function testEntityCreateRenameBundle() {
     entity_create('field_instance', $this->instance_definition)->save();
 
     // Save an entity with data in the field.
-    $entity = entity_create($entity_type, array('id' => 0, 'revision_id' => 0, 'type' => $this->instance['bundle']));
-    $values = $this->_generateTestFieldValues($this->field['cardinality']);
+    $entity = entity_create($entity_type, array('id' => 0, 'revision_id' => 0, 'type' => $this->instance->bundle));
+    $values = $this->_generateTestFieldValues($this->field->getFieldCardinality());
     $entity->{$this->field_name} = $values;
     field_attach_insert($entity);
 
     // Verify the field data is present on load.
-    $entity = entity_create($entity_type, array('id' => 0, 'revision_id' => 0, 'type' => $this->instance['bundle']));
+    $entity = entity_create($entity_type, array('id' => 0, 'revision_id' => 0, 'type' => $this->instance->bundle));
     field_attach_load($entity_type, array(0 => $entity));
-    $this->assertEqual(count($entity->{$this->field_name}), $this->field['cardinality'], "Data is retrieved for the new bundle");
+    $this->assertEqual(count($entity->{$this->field_name}), $this->field->getFieldCardinality(), "Data is retrieved for the new bundle");
 
     // Rename the bundle.
     $new_bundle = 'test_bundle_' . drupal_strtolower($this->randomName());
@@ -451,12 +452,12 @@ function testEntityCreateRenameBundle() {
 
     // Check that the instance definition has been updated.
     $this->instance = field_info_instance($entity_type, $this->field_name, $new_bundle);
-    $this->assertIdentical($this->instance['bundle'], $new_bundle, "Bundle name has been updated in the instance.");
+    $this->assertIdentical($this->instance->bundle, $new_bundle, "Bundle name has been updated in the instance.");
 
     // Verify the field data is present on load.
-    $entity = entity_create($entity_type, array('id' => 0, 'revision_id' => 0, 'type' => $this->instance['bundle']));
+    $entity = entity_create($entity_type, array('id' => 0, 'revision_id' => 0, 'type' => $this->instance->bundle));
     field_attach_load($entity_type, array(0 => $entity));
-    $this->assertEqual(count($entity->{$this->field_name}), $this->field['cardinality'], "Bundle name has been updated in the field storage");
+    $this->assertEqual(count($entity->{$this->field_name}), $this->field->getFieldCardinality(), "Bundle name has been updated in the field storage");
   }
 
   /**
@@ -481,7 +482,7 @@ function testEntityDeleteBundle() {
     $instance = array(
       'field_name' => $field_name,
       'entity_type' => $entity_type,
-      'bundle' => $this->instance['bundle'],
+      'bundle' => $this->instance->bundle,
       'label' => $this->randomName() . '_label',
       'description' => $this->randomName() . '_description',
       'weight' => mt_rand(0, 127),
@@ -489,29 +490,29 @@ function testEntityDeleteBundle() {
     entity_create('field_instance', $instance)->save();
 
     // Save an entity with data for both fields
-    $entity = entity_create($entity_type, array('id' => 0, 'revision_id' => 0, 'type' => $this->instance['bundle']));
-    $values = $this->_generateTestFieldValues($this->field['cardinality']);
+    $entity = entity_create($entity_type, array('id' => 0, 'revision_id' => 0, 'type' => $this->instance->bundle));
+    $values = $this->_generateTestFieldValues($this->field->getFieldCardinality());
     $entity->{$this->field_name} = $values;
     $entity->{$field_name} = $this->_generateTestFieldValues(1);
     field_attach_insert($entity);
 
     // Verify the fields are present on load
-    $entity = entity_create($entity_type, array('id' => 0, 'revision_id' => 0, 'type' => $this->instance['bundle']));
+    $entity = entity_create($entity_type, array('id' => 0, 'revision_id' => 0, 'type' => $this->instance->bundle));
     field_attach_load($entity_type, array(0 => $entity));
     $this->assertEqual(count($entity->{$this->field_name}), 4, 'First field got loaded');
     $this->assertEqual(count($entity->{$field_name}), 1, 'Second field got loaded');
 
     // Delete the bundle.
-    entity_test_delete_bundle($this->instance['bundle'], $entity_type);
+    entity_test_delete_bundle($this->instance->bundle, $entity_type);
 
     // Verify no data gets loaded
-    $entity = entity_create($entity_type, array('id' => 0, 'revision_id' => 0, 'type' => $this->instance['bundle']));
+    $entity = entity_create($entity_type, array('id' => 0, 'revision_id' => 0, 'type' => $this->instance->bundle));
     field_attach_load($entity_type, array(0 => $entity));
     $this->assertTrue(empty($entity->{$this->field_name}), 'No data for first field');
     $this->assertTrue(empty($entity->{$field_name}), 'No data for second field');
 
     // Verify that the instances are gone
-    $this->assertFalse(field_read_instance('entity_test', $this->field_name, $this->instance['bundle']), "First field is deleted");
+    $this->assertFalse(field_read_instance('entity_test', $this->field_name, $this->instance->bundle), "First field is deleted");
     $this->assertFalse(field_read_instance('entity_test', $field_name, $instance['bundle']), "Second field is deleted");
   }
 
diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldImportChangeTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldImportChangeTest.php
index 6e4b8b8..5c686be 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FieldImportChangeTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FieldImportChangeTest.php
@@ -52,7 +52,7 @@ function testImportChange() {
 
     // Check that the updated config was correctly imported.
     $instance = entity_load('field_instance', $instance_id);
-    $this->assertEqual($instance['label'], $new_label, 'Instance label updated');
+    $this->assertEqual($instance->label, $new_label, 'Instance label updated');
   }
 }
 
diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php
index 70f99f1..15a0fa8 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php
@@ -57,19 +57,19 @@ function testFieldInfo() {
     $field->save();
     $fields = field_info_fields();
     $this->assertEqual(count($fields), count($core_fields) + 1, 'One new field exists');
-    $this->assertEqual($fields[$field['field_name']]['field_name'], $field['field_name'], 'info fields contains field name');
-    $this->assertEqual($fields[$field['field_name']]['type'], $field['type'], 'info fields contains field type');
-    $this->assertEqual($fields[$field['field_name']]['module'], 'field_test', 'info fields contains field module');
+    $this->assertEqual($fields[$field->getFieldName()]->id(), $field->getFieldName(), 'info fields contains field name');
+    $this->assertEqual($fields[$field->getFieldName()]->getFieldType(), $field->getFieldType(), 'info fields contains field type');
+    $this->assertEqual($fields[$field->getFieldName()]->module, 'field_test', 'info fields contains field module');
     $settings = array('test_field_setting' => 'dummy test string');
     foreach ($settings as $key => $val) {
-      $this->assertEqual($fields[$field['field_name']]['settings'][$key], $val, format_string('Field setting %key has correct default value %value', array('%key' => $key, '%value' => $val)));
+      $this->assertEqual($fields[$field->getFieldName()]->settings[$key], $val, format_string('Field setting %key has correct default value %value', array('%key' => $key, '%value' => $val)));
     }
-    $this->assertEqual($fields[$field['field_name']]['cardinality'], 1, 'info fields contains cardinality 1');
-    $this->assertEqual($fields[$field['field_name']]['active'], TRUE, 'info fields contains active 1');
+    $this->assertEqual($fields[$field->getFieldName()]->getFieldCardinality(), 1, 'info fields contains cardinality 1');
+    $this->assertEqual($fields[$field->getFieldName()]->active, TRUE, 'info fields contains active 1');
 
     // Create an instance, verify that it shows up
     $instance_definition = array(
-      'field_name' => $field['field_name'],
+      'field_name' => $field->getFieldName(),
       'entity_type' => 'entity_test',
       'bundle' => 'entity_test',
       'label' => $this->randomName(),
@@ -80,18 +80,18 @@ function testFieldInfo() {
     $instance->save();
 
     $info = entity_get_info('entity_test');
-    $instances = field_info_instances('entity_test', $instance['bundle']);
+    $instances = field_info_instances('entity_test', $instance->bundle);
     $this->assertEqual(count($instances), 1, format_string('One instance shows up in info when attached to a bundle on a @label.', array(
       '@label' => $info['label']
     )));
-    $this->assertTrue($instance_definition < $instances[$instance['field_name']], 'Instance appears in info correctly');
+    $this->assertTrue($instance_definition < $instances[$instance->getFieldName()], 'Instance appears in info correctly');
 
     // Test a valid entity type but an invalid bundle.
     $instances = field_info_instances('entity_test', 'invalid_bundle');
     $this->assertIdentical($instances, array(), "field_info_instances('entity_test', 'invalid_bundle') returns an empty array.");
 
     // Test invalid entity type and bundle.
-    $instances = field_info_instances('invalid_entity', $instance['bundle']);
+    $instances = field_info_instances('invalid_entity', $instance->bundle);
     $this->assertIdentical($instances, array(), "field_info_instances('invalid_entity', 'entity_test') returns an empty array.");
 
     // Test invalid entity type, no bundle provided.
@@ -130,7 +130,7 @@ function testFieldPrepare() {
     // Simulate a stored field definition missing a field setting (e.g. a
     // third-party module adding a new field setting has been enabled, and
     // existing fields do not know the setting yet).
-    \Drupal::config('field.field.' . $field->id())
+    \Drupal::config('field.field.' . $field->getFieldName())
       ->set('settings', array())
       ->save();
     field_info_cache_clear();
@@ -140,7 +140,7 @@ function testFieldPrepare() {
 
     // Check that all expected settings are in place.
     $field_type = \Drupal::service('plugin.manager.entity.field.field_type')->getDefinition($field_definition['type']);
-    $this->assertEqual($field['settings'], $field_type['settings'], 'All expected default field settings are present.');
+    $this->assertEqual($field->settings, $field_type['settings'], 'All expected default field settings are present.');
   }
 
   /**
@@ -173,7 +173,7 @@ function testInstancePrepare() {
 
     // Check that all expected instance settings are in place.
     $field_type = \Drupal::service('plugin.manager.entity.field.field_type')->getDefinition($field_definition['type']);
-    $this->assertEqual($instance['settings'], $field_type['instance_settings'] , 'All expected instance settings are present.');
+    $this->assertEqual($instance->settings, $field_type['instance_settings'], 'All expected instance settings are present.');
   }
 
   /**
diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldInstanceCrudTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldInstanceCrudTest.php
index 0ba7eb5..5615708 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FieldInstanceCrudTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FieldInstanceCrudTest.php
@@ -50,7 +50,7 @@ function setUp() {
     $this->field = entity_create('field_entity', $this->field_definition);
     $this->field->save();
     $this->instance_definition = array(
-      'field_name' => $this->field['field_name'],
+      'field_name' => $this->field->getFieldName(),
       'entity_type' => 'entity_test',
       'bundle' => 'entity_test',
     );
@@ -148,9 +148,9 @@ function testReadFieldInstance() {
 
     // Read the instance back.
     $instance = field_read_instance('entity_test', $this->instance_definition['field_name'], $this->instance_definition['bundle']);
-    $this->assertTrue($this->instance_definition['field_name'] == $instance['field_name'], 'The field was properly read.');
-    $this->assertTrue($this->instance_definition['entity_type'] == $instance['entity_type'], 'The field was properly read.');
-    $this->assertTrue($this->instance_definition['bundle'] == $instance['bundle'], 'The field was properly read.');
+    $this->assertTrue($this->instance_definition['field_name'] == $instance->getFieldName(), 'The field was properly read.');
+    $this->assertTrue($this->instance_definition['entity_type'] == $instance->entity_type, 'The field was properly read.');
+    $this->assertTrue($this->instance_definition['bundle'] == $instance->bundle, 'The field was properly read.');
   }
 
   /**
@@ -161,16 +161,16 @@ function testUpdateFieldInstance() {
 
     // Check that basic changes are saved.
     $instance = field_read_instance('entity_test', $this->instance_definition['field_name'], $this->instance_definition['bundle']);
-    $instance['required'] = !$instance['required'];
-    $instance['label'] = $this->randomName();
-    $instance['description'] = $this->randomName();
-    $instance['settings']['test_instance_setting'] = $this->randomName();
+    $instance->required = !$instance->required;
+    $instance->label = $this->randomName();
+    $instance->description = $this->randomName();
+    $instance->settings['test_instance_setting'] = $this->randomName();
     $instance->save();
 
     $instance_new = field_read_instance('entity_test', $this->instance_definition['field_name'], $this->instance_definition['bundle']);
-    $this->assertEqual($instance['required'], $instance_new['required'], '"required" change is saved');
-    $this->assertEqual($instance['label'], $instance_new['label'], '"label" change is saved');
-    $this->assertEqual($instance['description'], $instance_new['description'], '"description" change is saved');
+    $this->assertEqual($instance->required, $instance_new->required, '"required" change is saved');
+    $this->assertEqual($instance->label(), $instance_new->label, '"label" change is saved');
+    $this->assertEqual($instance->description, $instance_new->description, '"description" change is saved');
 
     // TODO: test failures.
   }
@@ -192,13 +192,13 @@ function testDeleteFieldInstance() {
 
     // Test that the first instance is not deleted, and then delete it.
     $instance = field_read_instance('entity_test', $this->instance_definition['field_name'], $this->instance_definition['bundle'], array('include_deleted' => TRUE));
-    $this->assertTrue(!empty($instance) && empty($instance['deleted']), 'A new field instance is not marked for deletion.');
+    $this->assertTrue(!empty($instance) && empty($instance->deleted), 'A new field instance is not marked for deletion.');
     $instance->delete();
 
     // Make sure the instance is marked as deleted when the instance is
     // specifically loaded.
     $instance = field_read_instance('entity_test', $this->instance_definition['field_name'], $this->instance_definition['bundle'], array('include_deleted' => TRUE));
-    $this->assertTrue(!empty($instance['deleted']), 'A deleted field instance is marked for deletion.');
+    $this->assertTrue(!empty($instance->deleted), 'A deleted field instance is marked for deletion.');
 
     // Try to load the instance normally and make sure it does not show up.
     $instance = field_read_instance('entity_test', $this->instance_definition['field_name'], $this->instance_definition['bundle']);
@@ -206,13 +206,13 @@ function testDeleteFieldInstance() {
 
     // Make sure the other field instance is not deleted.
     $another_instance = field_read_instance('entity_test', $another_instance_definition['field_name'], $another_instance_definition['bundle']);
-    $this->assertTrue(!empty($another_instance) && empty($another_instance['deleted']), 'A non-deleted field instance is not marked for deletion.');
+    $this->assertTrue(!empty($another_instance) && empty($another_instance->deleted), 'A non-deleted field instance is not marked for deletion.');
 
     // Make sure the field is deleted when its last instance is deleted.
     $another_instance->delete();
     $deleted_fields = \Drupal::state()->get('field.field.deleted');
-    $this->assertTrue(isset($deleted_fields[$another_instance['field_id']]), 'A deleted field is marked for deletion.');
-    $field = field_read_field($another_instance['field_name']);
+    $this->assertTrue(isset($deleted_fields[$another_instance->getField()->uuid()]), 'A deleted field is marked for deletion.');
+    $field = field_read_field($another_instance->getFieldName());
     $this->assertFalse($field, 'The field marked to be deleted is not found anymore in the configuration.');
   }
 
diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldUnitTestBase.php b/core/modules/field/lib/Drupal/field/Tests/FieldUnitTestBase.php
index 4580e7b..8168e39 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FieldUnitTestBase.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FieldUnitTestBase.php
@@ -67,7 +67,7 @@ function createFieldWithInstance($suffix = '', $entity_type = 'entity_test', $bu
     $this->$field_name = drupal_strtolower($this->randomName() . '_field_name' . $suffix);
     $this->$field = entity_create('field_entity', array('field_name' => $this->$field_name, 'type' => 'test_field', 'cardinality' => 4));
     $this->$field->save();
-    $this->$field_id = $this->{$field}['uuid'];
+    $this->$field_id = $this->{$field}->uuid;
     $this->$instance_definition = array(
       'field_name' => $this->$field_name,
       'entity_type' => $entity_type,
diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldValidationTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldValidationTest.php
index 3dd2e32..df98b0c 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FieldValidationTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FieldValidationTest.php
@@ -54,14 +54,14 @@ function testCardinalityConstraint() {
     // Check that the expected constraint violations are reported.
     $this->assertEqual(count($violations), 1);
     $this->assertEqual($violations[0]->getPropertyPath(), '');
-    $this->assertEqual($violations[0]->getMessage(), t('%name: this field cannot hold more than @count values.', array('%name' => $this->instance['label'], '@count' => $cardinality)));
+    $this->assertEqual($violations[0]->getMessage(), t('%name: this field cannot hold more than @count values.', array('%name' => $this->instance->label(), '@count' => $cardinality)));
   }
 
   /**
    * Tests that constraints defined by the field type are validated.
    */
   function testFieldConstraints() {
-    $cardinality = $this->field->cardinality;
+    $cardinality = $this->field->getFieldCardinality();
     $entity = $this->entity;
 
     // The test is only valid if the field cardinality is greater than 2.
@@ -76,7 +76,7 @@ function testFieldConstraints() {
       }
       else {
         $value = -1;
-        $expected_violations[$delta . '.value'][] = t('%name does not accept the value -1.', array('%name' => $this->instance['label']));
+        $expected_violations[$delta . '.value'][] = t('%name does not accept the value -1.', array('%name' => $this->instance->label()));
       }
       $entity->{$this->field_name}->offsetGet($delta)->set('value', $value);
     }
diff --git a/core/modules/field/lib/Drupal/field/Tests/FormTest.php b/core/modules/field/lib/Drupal/field/Tests/FormTest.php
index b263859..c362084 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FormTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FormTest.php
@@ -585,8 +585,8 @@ function testFieldFormHiddenWidget() {
     entity_create('field_entity', $field)->save();
     $this->instance = entity_create('field_instance', $this->instance);
     $this->instance->save();
-    entity_get_form_display($this->instance['entity_type'], $this->instance['bundle'], 'default')
-      ->setComponent($this->instance['field_name'], array(
+    entity_get_form_display($this->instance->entity_type, $this->instance->bundle, 'default')
+      ->setComponent($this->instance->getFieldName(), array(
         'type' => 'hidden',
       ))
       ->save();
@@ -607,10 +607,10 @@ function testFieldFormHiddenWidget() {
 
     // Update the instance to remove the default value and switch to the
     // default widget.
-    $this->instance['default_value'] = NULL;
+    $this->instance->default_value = NULL;
     $this->instance->save();
-    entity_get_form_display($this->instance['entity_type'], $this->instance['bundle'], 'default')
-      ->setComponent($this->instance['field_name'], array(
+    entity_get_form_display($this->instance->entity_type, $this->instance->bundle, 'default')
+      ->setComponent($this->instance->getFieldName(), array(
         'type' => 'test_field_widget',
       ))
       ->save();
@@ -629,8 +629,8 @@ function testFieldFormHiddenWidget() {
     $this->assertEqual($entity->{$field_name}->value, $value, 'Field value was updated');
 
     // Update the form display and switch to the Hidden widget again.
-    entity_get_form_display($this->instance['entity_type'], $this->instance['bundle'], 'default')
-      ->setComponent($this->instance['field_name'], array(
+    entity_get_form_display($this->instance->entity_type, $this->instance->bundle, 'default')
+      ->setComponent($this->instance->getFieldName(), array(
         'type' => 'hidden',
       ))
       ->save();
diff --git a/core/modules/field/lib/Drupal/field/Tests/TranslationTest.php b/core/modules/field/lib/Drupal/field/Tests/TranslationTest.php
index 85c14e2..2beafe7 100644
--- a/core/modules/field/lib/Drupal/field/Tests/TranslationTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/TranslationTest.php
@@ -117,7 +117,7 @@ function testFieldAvailableLanguages() {
     // Test 'translatable' fieldable info.
     field_test_entity_info_translatable('entity_test', FALSE);
     $field = clone($this->field);
-    $field['field_name'] .= '_untranslatable';
+    $field->id .= '_untranslatable';
 
     // Enable field translations for the entity.
     field_test_entity_info_translatable('entity_test', TRUE);
@@ -135,7 +135,7 @@ function testFieldAvailableLanguages() {
     $this->assertFalse(in_array('en', $available_langcodes), format_string('%language was made unavailable.', array('%language' => 'en')));
 
     // Test field_available_languages() behavior for untranslatable fields.
-    $this->field['translatable'] = FALSE;
+    $this->field->translatable = FALSE;
     $this->field->save();
     $available_langcodes = field_available_languages($this->entity_type, $this->field);
     $this->assertTrue(count($available_langcodes) == 1 && $available_langcodes[0] === Language::LANGCODE_NOT_SPECIFIED, 'For untranslatable fields only Language::LANGCODE_NOT_SPECIFIED is available.');
@@ -154,19 +154,19 @@ function testTranslatableFieldSaveLoad() {
     $entity_type = 'entity_test';
     field_test_entity_info_translatable($entity_type, TRUE);
     $id = $revision_id = 1;
-    $entity = entity_create($entity_type, array('id' => $id, 'revision_id' => $revision_id, 'type' => $this->instance['bundle']));
+    $entity = entity_create($entity_type, array('id' => $id, 'revision_id' => $revision_id, 'type' => $this->instance->bundle));
     $field_translations = array();
     $available_langcodes = field_available_languages($entity_type, $this->field);
     $this->assertTrue(count($available_langcodes) > 1, 'Field is translatable.');
     $entity->langcode->value = reset($available_langcodes);
     foreach ($available_langcodes as $langcode) {
-      $field_translations[$langcode] = $this->_generateTestFieldValues($this->field['cardinality']);
+      $field_translations[$langcode] = $this->_generateTestFieldValues($this->field->getFieldCardinality());
       $entity->getTranslation($langcode)->{$this->field_name}->setValue($field_translations[$langcode]);
     }
 
     // Save and reload the field translations.
     field_attach_insert($entity);
-    $entity = entity_create($entity_type, array('id' => $id, 'revision_id' => $revision_id, 'type' => $this->instance['bundle']));
+    $entity = entity_create($entity_type, array('id' => $id, 'revision_id' => $revision_id, 'type' => $this->instance->bundle));
     $entity->langcode->value = reset($available_langcodes);
     field_attach_load($entity_type, array($id => $entity));
 
@@ -199,10 +199,10 @@ function testTranslatableFieldSaveLoad() {
 
     $id++;
     $revision_id++;
-    $values = array('id' => $id, 'revision_id' => $revision_id, 'type' => $instance['bundle'], 'langcode' => $translation_langcodes[0]);
+    $values = array('id' => $id, 'revision_id' => $revision_id, 'type' => $instance->bundle, 'langcode' => $translation_langcodes[0]);
     $entity = entity_create($entity_type, $values);
     foreach ($translation_langcodes as $langcode) {
-      $values[$this->field_name][$langcode] = $this->_generateTestFieldValues($this->field['cardinality']);
+      $values[$this->field_name][$langcode] = $this->_generateTestFieldValues($this->field->getFieldCardinality());
       $entity->getTranslation($langcode, FALSE)->{$this->field_name}->setValue($values[$this->field_name][$langcode]);
     }
 
@@ -213,16 +213,16 @@ function testTranslatableFieldSaveLoad() {
     // @todo Test every translation once the Entity Translation API allows for
     //   multilingual defaults.
     $langcode = $entity->language()->id;
-    $this->assertEqual($entity->getTranslation($langcode)->{$field_name_default}->getValue(), $instance['default_value'], format_string('Default value correctly populated for language %language.', array('%language' => $langcode)));
+    $this->assertEqual($entity->getTranslation($langcode)->{$field_name_default}->getValue(), $instance->default_value, format_string('Default value correctly populated for language %language.', array('%language' => $langcode)));
 
     // Check that explicit empty values are not overridden with default values.
     foreach (array(NULL, array()) as $empty_items) {
       $id++;
       $revision_id++;
-      $values = array('id' => $id, 'revision_id' => $revision_id, 'type' => $instance['bundle'], 'langcode' => $translation_langcodes[0]);
+      $values = array('id' => $id, 'revision_id' => $revision_id, 'type' => $instance->bundle, 'langcode' => $translation_langcodes[0]);
       $entity = entity_create($entity_type, $values);
       foreach ($translation_langcodes as $langcode) {
-        $values[$this->field_name][$langcode] = $this->_generateTestFieldValues($this->field['cardinality']);
+        $values[$this->field_name][$langcode] = $this->_generateTestFieldValues($this->field->getFieldCardinality());
         $entity->getTranslation($langcode)->{$this->field_name}->setValue($values[$this->field_name][$langcode]);
         $entity->getTranslation($langcode)->{$field_name_default}->setValue($empty_items);
         $values[$field_name_default][$langcode] = $empty_items;
@@ -259,9 +259,9 @@ function testFieldDisplayLanguage() {
     entity_create('field_instance', $instance)->save();
 
     $enabled_langcodes = field_content_languages();
-    $entity = entity_create($entity_type, array('id' => 1, 'revision_id' => 1, 'type' => $this->instance['bundle']));;
+    $entity = entity_create($entity_type, array('id' => 1, 'revision_id' => 1, 'type' => $this->instance->bundle));
     $entity->langcode->value = reset($enabled_langcodes);
-    $instances = field_info_instances($entity_type, $this->instance['bundle']);
+    $instances = field_info_instances($entity_type, $this->instance->bundle);
 
     $langcodes = array();
     // This array is used to store, for each field name, which one of the locked
@@ -271,7 +271,7 @@ function testFieldDisplayLanguage() {
     // Generate field translations for languages different from the first
     // enabled.
     foreach ($instances as $instance) {
-      $field_name = $instance['field_name'];
+      $field_name = $instance->getFieldName();
       $field = field_info_field($field_name);
       do {
         // Index 0 is reserved for the requested language, this way we ensure
@@ -280,7 +280,7 @@ function testFieldDisplayLanguage() {
       }
       while (isset($langcodes[$langcode]));
       $langcodes[$langcode] = TRUE;
-      $entity->getTranslation($langcode)->{$field_name}->setValue($this->_generateTestFieldValues($field['cardinality']));
+      $entity->getTranslation($langcode)->{$field_name}->setValue($this->_generateTestFieldValues($field->getFieldCardinality()));
       // If the langcode is one of the locked languages, then that one
       // will also be used for display. Otherwise, the default one should be
       // used, which is Language::LANGCODE_NOT_SPECIFIED.
@@ -298,7 +298,7 @@ function testFieldDisplayLanguage() {
     $requested_langcode = $enabled_langcodes[0];
     $display_langcodes = field_language($entity, NULL, $requested_langcode);
     foreach ($instances as $instance) {
-      $field_name = $instance['field_name'];
+      $field_name = $instance->getFieldName();
       $this->assertTrue($display_langcodes[$field_name] == $locked_languages[$field_name], format_string('The display language for field %field_name is %language.', array('%field_name' => $field_name, '%language' => $locked_languages[$field_name])));
     }
 
@@ -307,7 +307,7 @@ function testFieldDisplayLanguage() {
     drupal_static_reset('field_language');
     $display_langcodes = field_language($entity, NULL, $requested_langcode);
     foreach ($instances as $instance) {
-      $field_name = $instance['field_name'];
+      $field_name = $instance->getFieldName();
       $langcode = $display_langcodes[$field_name];
       // As the requested language was not assinged to any field, if the
       // returned language is defined for the current field, core fallback rules
diff --git a/core/modules/field/lib/Drupal/field/Tests/TranslationWebTest.php b/core/modules/field/lib/Drupal/field/Tests/TranslationWebTest.php
index 69b4c48..702ec8f 100644
--- a/core/modules/field/lib/Drupal/field/Tests/TranslationWebTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/TranslationWebTest.php
@@ -107,7 +107,7 @@ function testFieldFormTranslationRevisions() {
     $available_langcodes = array_flip(field_available_languages($this->entity_type, $this->field));
     unset($available_langcodes[Language::LANGCODE_NOT_SPECIFIED]);
     unset($available_langcodes[Language::LANGCODE_NOT_APPLICABLE]);
-    $field_name = $this->field['field_name'];
+    $field_name = $this->field->id();
 
     // Store the field translations.
     $entity->langcode->value = key($available_langcodes);
@@ -136,7 +136,7 @@ function testFieldFormTranslationRevisions() {
    * by the passed arguments were correctly stored.
    */
   private function checkTranslationRevisions($id, $revision_id, $available_langcodes) {
-    $field_name = $this->field['field_name'];
+    $field_name = $this->field->id();
     $entity = entity_revision_load($this->entity_type, $revision_id);
     foreach ($available_langcodes as $langcode => $value) {
       $passed = $entity->getTranslation($langcode)->{$field_name}->value == $value + 1;
diff --git a/core/modules/field/lib/Drupal/field/Tests/Views/FieldTestBase.php b/core/modules/field/lib/Drupal/field/Tests/Views/FieldTestBase.php
index 3cba44c..bbce87b 100644
--- a/core/modules/field/lib/Drupal/field/Tests/Views/FieldTestBase.php
+++ b/core/modules/field/lib/Drupal/field/Tests/Views/FieldTestBase.php
@@ -70,7 +70,7 @@ function setUpFields($amount = 3) {
   function setUpInstances($bundle = 'page') {
     foreach ($this->fields as $key => $field) {
       $instance = array(
-        'field_name' => $field['field_name'],
+        'field_name' => $field->id(),
         'entity_type' => 'node',
         'bundle' => 'page',
       );
diff --git a/core/modules/field/lib/Drupal/field/Tests/Views/HandlerFieldFieldTest.php b/core/modules/field/lib/Drupal/field/Tests/Views/HandlerFieldFieldTest.php
index c42950d..ff87a67 100644
--- a/core/modules/field/lib/Drupal/field/Tests/Views/HandlerFieldFieldTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/Views/HandlerFieldFieldTest.php
@@ -62,13 +62,13 @@ protected function setUp() {
 
       for ($key = 0; $key < 3; $key++) {
         $field = $this->fields[$key];
-        $edit[$field['field_name']][0]['value'] = $this->randomName(8);
+        $edit[$field->getFieldName()][0]['value'] = $this->randomName(8);
       }
       for ($j = 0; $j < 5; $j++) {
-        $edit[$this->fields[3]['field_name']][$j]['value'] = $this->randomName(8);
+        $edit[$this->fields[3]->getFieldName()][$j]['value'] = $this->randomName(8);
       }
       // Set this field to be empty.
-      $edit[$this->fields[4]['field_name']] = array(array('value' => NULL));
+      $edit[$this->fields[4]->getFieldName()] = array(array('value' => NULL));
 
       $this->nodes[$i] = $this->drupalCreateNode($edit);
     }
@@ -85,9 +85,9 @@ protected function setUp() {
   protected function prepareView(ViewExecutable $view) {
     $view->initDisplay();
     foreach ($this->fields as $key => $field) {
-      $view->display_handler->options['fields'][$field['field_name']]['id'] = $field['field_name'];
-      $view->display_handler->options['fields'][$field['field_name']]['table'] = 'field_data_' . $field['field_name'];
-      $view->display_handler->options['fields'][$field['field_name']]['field'] = $field['field_name'];
+      $view->display_handler->options['fields'][$field->getFieldName()]['id'] = $field->getFieldName();
+      $view->display_handler->options['fields'][$field->getFieldName()]['table'] = 'field_data_' . $field->getFieldName();
+      $view->display_handler->options['fields'][$field->getFieldName()]['field'] = $field->getFieldName();
     }
   }
 
@@ -106,8 +106,8 @@ public function _testSimpleFieldRender() {
     for ($i = 0; $i < 3; $i++) {
       for ($key = 0; $key < 2; $key++) {
         $field = $this->fields[$key];
-        $rendered_field = $view->style_plugin->getField($i, $field['field_name']);
-        $expected_field = $this->nodes[$i]->{$field['field_name']}->value;
+        $rendered_field = $view->style_plugin->getField($i, $field->getFieldName());
+        $expected_field = $this->nodes[$i]->{$field->getFieldName()}->value;
         $this->assertEqual($rendered_field, $expected_field);
       }
     }
@@ -135,7 +135,7 @@ public function _testFormatterSimpleFieldRender() {
 
   public function _testMultipleFieldRender() {
     $view = views_get_view('test_view_fieldapi');
-    $field_name = $this->fields[3]['field_name'];
+    $field_name = $this->fields[3]->getFieldName();
 
     // Test delta limit.
     $this->prepareView($view);
diff --git a/core/modules/field/tests/modules/field_test/field_test.field.inc b/core/modules/field/tests/modules/field_test/field_test.field.inc
index 3ac75fa..15e2e74 100644
--- a/core/modules/field/tests/modules/field_test/field_test.field.inc
+++ b/core/modules/field/tests/modules/field_test/field_test.field.inc
@@ -65,7 +65,7 @@ function field_test_field_widget_info_alter(&$info) {
  * Implements hook_field_update_forbid().
  */
 function field_test_field_update_forbid($field, $prior_field) {
-  if ($field['type'] == 'test_field' && $field['settings']['unchangeable'] != $prior_field['settings']['unchangeable']) {
+  if ($field->type == 'test_field' && $field->settings['unchangeable'] != $prior_field->settings['unchangeable']) {
     throw new FieldException("field_test 'unchangeable' setting cannot be changed'");
   }
 }
@@ -80,7 +80,7 @@ function field_test_field_load($entity_type, $entities, $field, $instances, $lan
   foreach ($items as $id => $item) {
     // To keep the test non-intrusive, only act for instances with the
     // test_hook_field_load setting explicitly set to TRUE.
-    if (!empty($instances[$id]['settings']['test_hook_field_load'])) {
+    if (!empty($instances[$id]->settings['test_hook_field_load'])) {
       foreach ($item as $delta => $value) {
         // Don't add anything on empty values.
         if ($value) {
@@ -127,9 +127,9 @@ function field_test_field_validate(EntityInterface $entity = NULL, $field, $inst
 
   foreach ($items as $delta => $item) {
     if ($item['value'] == -1) {
-      $errors[$field['field_name']][$langcode][$delta][] = array(
+      $errors[$field->id()][$langcode][$delta][] = array(
         'error' => 'field_test_invalid',
-        'message' => t('%name does not accept the value -1.', array('%name' => $instance['label'])),
+        'message' => t('%name does not accept the value -1.', array('%name' => $instance->label())),
       );
     }
   }
@@ -149,7 +149,7 @@ function field_test_field_is_empty($item, $field_type) {
  * Implements hook_field_settings_form().
  */
 function field_test_field_settings_form($field, $instance) {
-  $settings = $field['settings'];
+  $settings = $field->settings;
 
   $form['test_field_setting'] = array(
     '#type' => 'textfield',
@@ -166,7 +166,7 @@ function field_test_field_settings_form($field, $instance) {
  * Implements hook_field_instance_settings_form().
  */
 function field_test_field_instance_settings_form($field, $instance) {
-  $settings = $instance['settings'];
+  $settings = $instance->settings;
 
   $form['test_instance_setting'] = array(
     '#type' => 'textfield',
@@ -202,13 +202,13 @@ function field_test_default_value(EntityInterface $entity, $field, $instance) {
  * Implements hook_field_access().
  */
 function field_test_field_access($op, FieldInterface $field, $entity_type, $entity, $account) {
-  if ($field['field_name'] == "field_no_{$op}_access") {
+  if ($field->id() == "field_no_{$op}_access") {
     return FALSE;
   }
 
   // Only grant view access to test_view_field fields when the user has
   // 'view test_view_field content' permission.
-  if ($field['field_name'] == 'test_view_field' && $op == 'view' && !$account->hasPermission('view test_view_field content')) {
+  if ($field->getFieldName() == 'test_view_field' && $op == 'view' && !$account->hasPermission('view test_view_field content')) {
     return FALSE;
   }
 
diff --git a/core/modules/field/tests/modules/field_test/field_test.install b/core/modules/field/tests/modules/field_test/field_test.install
index a079829..5775380 100644
--- a/core/modules/field/tests/modules/field_test/field_test.install
+++ b/core/modules/field/tests/modules/field_test/field_test.install
@@ -17,7 +17,7 @@ function field_test_install() {
  * Implements hook_field_schema().
  */
 function field_test_field_schema($field) {
-  if ($field['type'] == 'test_field') {
+  if ($field->type == 'test_field') {
     return array(
       'columns' => array(
         'value' => array(
@@ -34,13 +34,13 @@ function field_test_field_schema($field) {
   else {
     $foreign_keys = array();
     // The 'foreign keys' key is not always used in tests.
-    if (!empty($field['settings']['foreign_key_name'])) {
+    if (!empty($field->settings['foreign_key_name'])) {
       $foreign_keys['foreign keys'] = array(
         // This is a dummy foreign key definition, references a table that
         // doesn't exist, but that's not a problem.
-        $field['settings']['foreign_key_name'] => array(
-          'table' => $field['settings']['foreign_key_name'],
-          'columns' => array($field['settings']['foreign_key_name'] => 'id'),
+        $field->settings['foreign_key_name'] => array(
+          'table' => $field->settings['foreign_key_name'],
+          'columns' => array($field->settings['foreign_key_name'] => 'id'),
         ),
       );
     }
diff --git a/core/modules/field/tests/modules/field_test/field_test.storage.inc b/core/modules/field/tests/modules/field_test/field_test.storage.inc
index 66c9911..2e4dd22 100644
--- a/core/modules/field/tests/modules/field_test/field_test.storage.inc
+++ b/core/modules/field/tests/modules/field_test/field_test.storage.inc
@@ -6,6 +6,7 @@
  */
 
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\field\FieldInterface;
 use Drupal\field\FieldInstanceInterface;
 
 /**
@@ -32,7 +33,7 @@ function field_test_field_storage_details($field) {
 
   // Add field columns.
   $columns = array();
-  foreach ((array) $field['columns'] as $column_name => $attributes) {
+  foreach ($field->getColumns() as $column_name => $attributes) {
     $columns[$column_name] = $column_name;
   }
   return array(
@@ -48,12 +49,12 @@ function field_test_field_storage_details($field) {
  *
  * @see FieldAttachStorageTestCase::testFieldStorageDetailsAlter()
  */
-function field_test_field_storage_details_alter(&$details, $field) {
+function field_test_field_storage_details_alter(&$details, FieldInterface $field) {
 
   // For testing, storage details are changed only because of the field name.
-  if ($field['field_name'] == 'field_test_change_my_details') {
+  if ($field->getFieldName() == 'field_test_change_my_details') {
     $columns = array();
-    foreach ((array) $field['columns'] as $column_name => $attributes) {
+    foreach ($field->getColumns() as $column_name => $attributes) {
       $columns[$column_name] = $column_name;
     }
     $details['drupal_variables'] = array(
@@ -89,8 +90,8 @@ function field_test_field_storage_load($entity_type, $entities, $age, $fields, $
 
   foreach ($fields as $field_id => $ids) {
     $field = field_info_field_by_id($field_id);
-    $field_name = $field['field_name'];
-    $field_data = $data[$field['uuid']];
+    $field_name = $field->getFieldName();
+    $field_data = $data[$field->uuid()];
     $sub_table = $load_current ? 'current' : 'revisions';
     $delta_count = array();
     foreach ($field_data[$sub_table] as $row) {
@@ -100,9 +101,9 @@ function field_test_field_storage_load($entity_type, $entities, $age, $fields, $
             if (!isset($delta_count[$row->entity_id][$row->langcode])) {
               $delta_count[$row->entity_id][$row->langcode] = 0;
             }
-            if ($field['cardinality'] == FIELD_CARDINALITY_UNLIMITED || $delta_count[$row->entity_id][$row->langcode] < $field['cardinality']) {
+            if ($field->getFieldCardinality() == FIELD_CARDINALITY_UNLIMITED || $delta_count[$row->entity_id][$row->langcode] < $field->getFieldCardinality()) {
               $item = array();
-              foreach ($field['columns'] as $column => $attributes) {
+              foreach ($field->getColumns() as $column => $attributes) {
                 $item[$column] = $row->{$column};
               }
               $entities[$row->entity_id]->{$field_name}[$row->langcode][] = $item;
@@ -127,7 +128,7 @@ function field_test_field_storage_write(EntityInterface $entity, $op, $fields) {
 
   foreach ($fields as $field_id) {
     $field = field_info_field_by_id($field_id);
-    $field_name = $field['field_name'];
+    $field_name = $field->getFieldName();
     $field_data = &$data[$field_id];
 
     $all_langcodes = field_available_languages($entity->entityType(), $field);
@@ -168,7 +169,7 @@ function field_test_field_storage_write(EntityInterface $entity, $op, $fields) {
           'deleted' => FALSE,
           'langcode' => $langcode,
         );
-        foreach ($field['columns'] as $column => $attributes) {
+        foreach ($field->getColumns() as $column => $attributes) {
           $row->{$column} = isset($item[$column]) ? $item[$column] : NULL;
         }
 
@@ -177,7 +178,7 @@ function field_test_field_storage_write(EntityInterface $entity, $op, $fields) {
           $field_data['revisions'][] = $row;
         }
 
-        if ($field['cardinality'] != FIELD_CARDINALITY_UNLIMITED && ++$delta_count == $field['cardinality']) {
+        if ($field->getFieldCardinality() != FIELD_CARDINALITY_UNLIMITED && ++$delta_count == $field->getFieldCardinality()) {
           break;
         }
       }
@@ -194,8 +195,8 @@ function field_test_field_storage_delete(EntityInterface $entity, $fields) {
   // Note: reusing field_test_storage_purge(), like field_sql_storage.module
   // does, is highly inefficient in our case...
   foreach (field_info_instances($entity->entityType(), $entity->bundle()) as $instance) {
-    if (isset($fields[$instance['field_id']])) {
-      $field = field_info_field_by_id($instance['field_id']);
+    if (isset($fields[$instance->getField()->uuid()])) {
+      $field = field_info_field_by_id($instance->getField()->uuid());
       field_test_field_storage_purge($entity, $field, $instance);
     }
   }
@@ -367,13 +368,13 @@ function _field_test_field_storage_query_sort_helper($a, $b) {
  * Implements hook_field_storage_create_field().
  */
 function field_test_field_storage_create_field($field) {
-  if ($field['storage']['type'] == 'field_test_storage_failure') {
+  if ($field->storage['type'] == 'field_test_storage_failure') {
     throw new Exception('field_test_storage_failure engine always fails to create fields');
   }
 
   $data = _field_test_storage_data();
 
-  $data[$field['uuid']] = array(
+  $data[$field->uuid()] = array(
     'current' => array(),
     'revisions' => array(),
   );
@@ -387,7 +388,7 @@ function field_test_field_storage_create_field($field) {
 function field_test_field_storage_delete_field($field) {
   $data = _field_test_storage_data();
 
-  $field_data = &$data[$field['uuid']];
+  $field_data = &$data[$field->uuid()];
   foreach (array('current', 'revisions') as $sub_table) {
     foreach ($field_data[$sub_table] as &$row) {
       $row->deleted = TRUE;
@@ -403,11 +404,11 @@ function field_test_field_storage_delete_field($field) {
 function field_test_field_storage_delete_instance($instance) {
   $data = _field_test_storage_data();
 
-  $field = field_info_field($instance['field_name']);
-  $field_data = &$data[$field['uuid']];
+  $field = field_info_field($instance->getFieldName());
+  $field_data = &$data[$field->uuid()];
   foreach (array('current', 'revisions') as $sub_table) {
     foreach ($field_data[$sub_table] as &$row) {
-      if ($row->bundle == $instance['bundle']) {
+      if ($row->bundle == $instance->bundle) {
         $row->deleted = TRUE;
       }
     }
@@ -425,9 +426,9 @@ function field_test_entity_bundle_rename($entity_type, $bundle_old, $bundle_new)
   // We need to account for deleted or inactive fields and instances.
   $instances = field_read_instances(array('bundle' => $bundle_new), array('include_deleted' => TRUE, 'include_inactive' => TRUE));
   foreach ($instances as $field_name => $instance) {
-    $field = field_info_field_by_id($instance['field_id']);
-    if ($field && $field['storage']['type'] == 'field_test_storage') {
-      $field_data = &$data[$field['uuid']];
+    $field = field_info_field_by_id($instance->getField()->uuid());
+    if ($field && $field->storage['type'] == 'field_test_storage') {
+      $field_data = &$data[$field->uuid()];
       foreach (array('current', 'revisions') as $sub_table) {
         foreach ($field_data[$sub_table] as &$row) {
           if ($row->bundle == $bundle_old) {
@@ -449,7 +450,7 @@ function field_test_field_instance_delete(FieldInstanceInterface $field_instance
 
   $field = $field_instance->getField();
   if ($field->storage['type'] == 'field_test_storage') {
-    $field_data = &$data[$field->uuid];
+    $field_data = &$data[$field->uuid()];
     foreach (array('current', 'revisions') as $sub_table) {
       foreach ($field_data[$sub_table] as &$row) {
         if ($row->bundle == $field_instance->bundle) {
diff --git a/core/modules/field_sql_storage/field_sql_storage.module b/core/modules/field_sql_storage/field_sql_storage.module
index 3e5e25f..83d2334 100644
--- a/core/modules/field_sql_storage/field_sql_storage.module
+++ b/core/modules/field_sql_storage/field_sql_storage.module
@@ -9,6 +9,7 @@
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\field\FieldUpdateForbiddenException;
 use Drupal\field\Entity\Field;
+use Drupal\field\FieldInterface;
 
 /**
  * Implements hook_help().
@@ -49,12 +50,12 @@ function field_sql_storage_field_storage_info() {
  * @return
  *   A string containing the generated name for the database table.
  */
-function _field_sql_storage_tablename($field) {
-  if ($field['deleted']) {
-    return "field_deleted_data_" . substr(hash('sha256', $field['uuid']), 0, 10);
+function _field_sql_storage_tablename(FieldInterface $field) {
+  if ($field->deleted) {
+    return "field_deleted_data_" . substr(hash('sha256', $field->uuid), 0, 10);
   }
   else {
-    return "field_data_{$field['field_name']}";
+    return "field_data_{$field->getFieldName()}";
   }
 }
 
@@ -72,12 +73,12 @@ function _field_sql_storage_tablename($field) {
  * @return
  *   A string containing the generated name for the database table.
  */
-function _field_sql_storage_revision_tablename($field) {
-  if ($field['deleted']) {
-    return "field_deleted_revision_" . substr(hash('sha256', $field['uuid']), 0, 10);
+function _field_sql_storage_revision_tablename(FieldInterface $field) {
+  if ($field->deleted) {
+    return "field_deleted_revision_" . substr(hash('sha256', $field->uuid), 0, 10);
   }
   else {
-    return "field_revision_{$field['field_name']}";
+    return "field_revision_{$field->id()}";
   }
 }
 
@@ -125,10 +126,10 @@ function _field_sql_storage_indexname($name, $index) {
  * @return
  *   One or more tables representing the schema for the field.
  */
-function _field_sql_storage_schema($field) {
-  $deleted = $field['deleted'] ? 'deleted ' : '';
+function _field_sql_storage_schema(FieldInterface $field) {
+  $deleted = $field->deleted ? 'deleted ' : '';
   $current = array(
-    'description' => "Data storage for {$deleted}field {$field['id']} ({$field['field_name']})",
+    'description' => "Data storage for {$deleted}field {$field->id()} ({$field->id()})",
     'fields' => array(
       'entity_type' => array(
         'type' => 'varchar',
@@ -193,41 +194,41 @@ function _field_sql_storage_schema($field) {
 
   // Add field columns.
   foreach ($schema['columns'] as $column_name => $attributes) {
-    $real_name = _field_sql_storage_columnname($field['field_name'], $column_name);
+    $real_name = _field_sql_storage_columnname($field->id(), $column_name);
     $current['fields'][$real_name] = $attributes;
   }
 
   // Add indexes.
   foreach ($schema['indexes'] as $index_name => $columns) {
-    $real_name = _field_sql_storage_indexname($field['field_name'], $index_name);
+    $real_name = _field_sql_storage_indexname($field->id(), $index_name);
     foreach ($columns as $column_name) {
       // Indexes can be specified as either a column name or an array with
       // column name and length. Allow for either case.
       if (is_array($column_name)) {
         $current['indexes'][$real_name][] = array(
-          _field_sql_storage_columnname($field['field_name'], $column_name[0]),
+          _field_sql_storage_columnname($field->id(), $column_name[0]),
           $column_name[1],
         );
       }
       else {
-        $current['indexes'][$real_name][] = _field_sql_storage_columnname($field['field_name'], $column_name);
+        $current['indexes'][$real_name][] = _field_sql_storage_columnname($field->id(), $column_name);
       }
     }
   }
 
   // Add foreign keys.
   foreach ($schema['foreign keys'] as $specifier => $specification) {
-    $real_name = _field_sql_storage_indexname($field['field_name'], $specifier);
+    $real_name = _field_sql_storage_indexname($field->id(), $specifier);
     $current['foreign keys'][$real_name]['table'] = $specification['table'];
     foreach ($specification['columns'] as $column_name => $referenced) {
-      $sql_storage_column = _field_sql_storage_columnname($field['field_name'], $column_name);
+      $sql_storage_column = _field_sql_storage_columnname($field->id(), $column_name);
       $current['foreign keys'][$real_name]['columns'][$sql_storage_column] = $referenced;
     }
   }
 
   // Construct the revision table.
   $revision = $current;
-  $revision['description'] = "Revision archive storage for {$deleted}field {$field['id']} ({$field['field_name']})";
+  $revision['description'] = "Revision archive storage for {$deleted}field {$field->id()} ({$field->id()})";
   $revision['primary key'] = array('entity_type', 'entity_id', 'revision_id', 'deleted', 'delta', 'langcode');
   $revision['fields']['revision_id']['not null'] = TRUE;
   $revision['fields']['revision_id']['description'] = 'The entity revision id this data is attached to';
@@ -241,7 +242,7 @@ function _field_sql_storage_schema($field) {
 /**
  * Implements hook_field_storage_create_field().
  */
-function field_sql_storage_field_storage_create_field($field) {
+function field_sql_storage_field_storage_create_field(FieldInterface $field) {
   $schema = _field_sql_storage_schema($field);
   foreach ($schema as $name => $table) {
     db_create_table($name, $table);
@@ -256,8 +257,8 @@ function field_sql_storage_field_storage_create_field($field) {
  * Forbids any field update that changes column definitions if there is any
  * data.
  */
-function field_sql_storage_field_update_forbid($field, $prior_field) {
-  if ($field->hasData() && $field['columns'] != $prior_field['columns']) {
+function field_sql_storage_field_update_forbid(FieldInterface $field, FieldInterface $prior_field) {
+  if ($field->hasData() && $field->getColumns() != $prior_field->getColumns()) {
     throw new FieldUpdateForbiddenException("field_sql_storage cannot change the schema for an existing field with data.");
   }
 }
@@ -265,7 +266,7 @@ function field_sql_storage_field_update_forbid($field, $prior_field) {
 /**
  * Implements hook_field_storage_update_field().
  */
-function field_sql_storage_field_storage_update_field($field, $prior_field) {
+function field_sql_storage_field_storage_update_field(FieldInterface $field, FieldInterface $prior_field) {
   if (!$field->hasData()) {
     // There is no data. Re-create the tables completely.
 
@@ -313,7 +314,7 @@ function field_sql_storage_field_storage_update_field($field, $prior_field) {
 
     foreach ($prior_schema['indexes'] as $name => $columns) {
       if (!isset($schema['indexes'][$name]) || $columns != $schema['indexes'][$name]) {
-        $real_name = _field_sql_storage_indexname($field['field_name'], $name);
+        $real_name = _field_sql_storage_indexname($field->id(), $name);
         db_drop_index($table, $real_name);
         db_drop_index($revision_table, $real_name);
       }
@@ -322,19 +323,19 @@ function field_sql_storage_field_storage_update_field($field, $prior_field) {
     $revision_table = _field_sql_storage_revision_tablename($field);
     foreach ($schema['indexes'] as $name => $columns) {
       if (!isset($prior_schema['indexes'][$name]) || $columns != $prior_schema['indexes'][$name]) {
-        $real_name = _field_sql_storage_indexname($field['field_name'], $name);
+        $real_name = _field_sql_storage_indexname($field->id(), $name);
         $real_columns = array();
         foreach ($columns as $column_name) {
           // Indexes can be specified as either a column name or an array with
           // column name and length. Allow for either case.
           if (is_array($column_name)) {
             $real_columns[] = array(
-              _field_sql_storage_columnname($field['field_name'], $column_name[0]),
+              _field_sql_storage_columnname($field->id(), $column_name[0]),
               $column_name[1],
             );
           }
           else {
-            $real_columns[] = _field_sql_storage_columnname($field['field_name'], $column_name);
+            $real_columns[] = _field_sql_storage_columnname($field->id(), $column_name);
           }
         }
         db_add_index($table, $real_name, $real_columns);
@@ -350,7 +351,7 @@ function field_sql_storage_field_storage_update_field($field, $prior_field) {
  */
 function field_sql_storage_field_storage_delete_field($field) {
   // Mark all data associated with the field for deletion.
-  $field['deleted'] = FALSE;
+  $field->deleted = FALSE;
   $table = _field_sql_storage_tablename($field);
   $revision_table = _field_sql_storage_revision_tablename($field);
   db_update($table)
@@ -358,7 +359,7 @@ function field_sql_storage_field_storage_delete_field($field) {
     ->execute();
 
   // Move the table to a unique name while the table contents are being deleted.
-  $field['deleted'] = TRUE;
+  $field->deleted = TRUE;
   $new_table = _field_sql_storage_tablename($field);
   $revision_new_table = _field_sql_storage_revision_tablename($field);
   db_rename_table($table, $new_table);
@@ -378,7 +379,7 @@ function field_sql_storage_field_storage_load($entity_type, $entities, $age, $fi
     // on each field individually is more efficient than loading all fields in
     // memory upfront with field_info_field_by_ids().
     $field = field_info_field_by_id($field_id);
-    $field_name = $field['field_name'];
+    $field_name = $field->id();
     $table = $load_current ? _field_sql_storage_tablename($field) : _field_sql_storage_revision_tablename($field);
 
     $query = db_select($table, 't')
@@ -400,11 +401,11 @@ function field_sql_storage_field_storage_load($entity_type, $entities, $age, $fi
         $delta_count[$row->entity_id][$row->langcode] = 0;
       }
 
-      if ($field['cardinality'] == FIELD_CARDINALITY_UNLIMITED || $delta_count[$row->entity_id][$row->langcode] < $field['cardinality']) {
+      if ($field->getFieldCardinality() == FIELD_CARDINALITY_UNLIMITED || $delta_count[$row->entity_id][$row->langcode] < $field->getFieldCardinality()) {
         $item = array();
         // For each column declared by the field, populate the item
         // from the prefixed database column.
-        foreach ($field['columns'] as $column => $attributes) {
+        foreach ($field->getColumns() as $column => $attributes) {
           $column_name = _field_sql_storage_columnname($field_name, $column);
           // Unserialize the value if specified in the column schema.
           $item[$column] = (!empty($attributes['serialize'])) ? unserialize($row->$column_name) : $row->$column_name;
@@ -432,7 +433,7 @@ function field_sql_storage_field_storage_write(EntityInterface $entity, $op, $fi
 
   foreach ($fields as $field_id) {
     $field = field_info_field_by_id($field_id);
-    $field_name = $field['field_name'];
+    $field_name = $field->id();
     $table_name = _field_sql_storage_tablename($field);
     $revision_name = _field_sql_storage_revision_tablename($field);
 
@@ -466,7 +467,7 @@ function field_sql_storage_field_storage_write(EntityInterface $entity, $op, $fi
     // Prepare the multi-insert query.
     $do_insert = FALSE;
     $columns = array('entity_type', 'entity_id', 'revision_id', 'bundle', 'delta', 'langcode');
-    foreach ($field['columns'] as $column => $attributes) {
+    foreach ($field->getColumns() as $column => $attributes) {
       $columns[] = _field_sql_storage_columnname($field_name, $column);
     }
     $query = db_insert($table_name)->fields($columns);
@@ -486,7 +487,7 @@ function field_sql_storage_field_storage_write(EntityInterface $entity, $op, $fi
           'delta' => $delta,
           'langcode' => $langcode,
         );
-        foreach ($field['columns'] as $column => $attributes) {
+        foreach ($field->getColumns() as $column => $attributes) {
           $column_name = _field_sql_storage_columnname($field_name, $column);
           $value = isset($item[$column]) ? $item[$column] : NULL;
           // Serialize the value if specified in the column schema.
@@ -497,7 +498,7 @@ function field_sql_storage_field_storage_write(EntityInterface $entity, $op, $fi
           $revision_query->values($record);
         }
 
-        if ($field['cardinality'] != FIELD_CARDINALITY_UNLIMITED && ++$delta_count == $field['cardinality']) {
+        if ($field->getFieldCardinality() != FIELD_CARDINALITY_UNLIMITED && ++$delta_count == $field->getFieldCardinality()) {
           break;
         }
       }
@@ -522,8 +523,8 @@ function field_sql_storage_field_storage_write(EntityInterface $entity, $op, $fi
  */
 function field_sql_storage_field_storage_delete(EntityInterface $entity, $fields) {
   foreach (field_info_instances($entity->entityType(), $entity->bundle()) as $instance) {
-    if (isset($fields[$instance['field_id']])) {
-      $field = field_info_field_by_id($instance['field_id']);
+    if (isset($fields[$instance->getField()->uuid])) {
+      $field = field_info_field_by_id($instance->getField()->uuid);
       field_sql_storage_field_storage_purge($entity, $field, $instance);
     }
   }
@@ -574,18 +575,18 @@ function field_sql_storage_field_storage_delete_revision(EntityInterface $entity
  * This function simply marks for deletion all data associated with the field.
  */
 function field_sql_storage_field_storage_delete_instance($instance) {
-  $field = field_info_field($instance['field_name']);
+  $field = field_info_field($instance->getFieldName());
   $table_name = _field_sql_storage_tablename($field);
   $revision_name = _field_sql_storage_revision_tablename($field);
   db_update($table_name)
     ->fields(array('deleted' => 1))
-    ->condition('entity_type', $instance['entity_type'])
-    ->condition('bundle', $instance['bundle'])
+    ->condition('entity_type', $instance->entity_type)
+    ->condition('bundle', $instance->bundle)
     ->execute();
   db_update($revision_name)
     ->fields(array('deleted' => 1))
-    ->condition('entity_type', $instance['entity_type'])
-    ->condition('bundle', $instance['bundle'])
+    ->condition('entity_type', $instance->entity_type)
+    ->condition('bundle', $instance->bundle)
     ->execute();
 }
 
@@ -596,8 +597,8 @@ function field_sql_storage_entity_bundle_rename($entity_type, $bundle_old, $bund
   // We need to account for deleted or inactive fields and instances.
   $instances = field_read_instances(array('entity_type' => $entity_type, 'bundle' => $bundle_new), array('include_deleted' => TRUE, 'include_inactive' => TRUE));
   foreach ($instances as $instance) {
-    $field = field_info_field_by_id($instance['field_id']);
-    if ($field['storage']['type'] == 'field_sql_storage') {
+    $field = field_info_field_by_id($instance->getField()->uuid);
+    if ($field->storage['type'] == 'field_sql_storage') {
       $table_name = _field_sql_storage_tablename($field);
       $revision_name = _field_sql_storage_revision_tablename($field);
       db_update($table_name)
@@ -620,7 +621,7 @@ function field_sql_storage_entity_bundle_rename($entity_type, $bundle_old, $bund
  * All field data items and instances have already been purged, so all that is
  * left is to delete the table.
  */
-function field_sql_storage_field_storage_purge_field($field) {
+function field_sql_storage_field_storage_purge_field(FieldInterface $field) {
   $table_name = _field_sql_storage_tablename($field);
   $revision_name = _field_sql_storage_revision_tablename($field);
   db_drop_table($table_name);
@@ -630,12 +631,13 @@ function field_sql_storage_field_storage_purge_field($field) {
 /**
  * Implements hook_field_storage_details().
  */
-function field_sql_storage_field_storage_details($field) {
+function field_sql_storage_field_storage_details(FieldInterface $field) {
   $details = array();
-  if (!empty($field['columns'])) {
+  $columns = $field->getColumns();
+  if (!empty($columns)) {
      // Add field columns.
-    foreach ($field['columns'] as $column_name => $attributes) {
-      $real_name = _field_sql_storage_columnname($field['field_name'], $column_name);
+    foreach ($columns as $column_name => $attributes) {
+      $real_name = _field_sql_storage_columnname($field->id(), $column_name);
       $columns[$column_name] = $real_name;
     }
     return array(
diff --git a/core/modules/field_sql_storage/lib/Drupal/field_sql_storage/Tests/FieldSqlStorageTest.php b/core/modules/field_sql_storage/lib/Drupal/field_sql_storage/Tests/FieldSqlStorageTest.php
index 58d64b2..bf5e685 100644
--- a/core/modules/field_sql_storage/lib/Drupal/field_sql_storage/Tests/FieldSqlStorageTest.php
+++ b/core/modules/field_sql_storage/lib/Drupal/field_sql_storage/Tests/FieldSqlStorageTest.php
@@ -102,7 +102,7 @@ function testFieldAttachLoad() {
     for ($evid = 0; $evid < 4; ++$evid) {
       $values[$evid] = array();
       // Note: we insert one extra value ('<=' instead of '<').
-      for ($delta = 0; $delta <= $this->field['cardinality']; $delta++) {
+      for ($delta = 0; $delta <= $this->field->getFieldCardinality(); $delta++) {
         $value = mt_rand(1, 127);
         $values[$evid][] = $value;
         $query->values(array($entity_type, $eid, $evid, $delta, $langcode, $value));
@@ -124,7 +124,7 @@ function testFieldAttachLoad() {
     ));
     field_attach_load($entity_type, array($eid => $entity));
     foreach ($values[0] as $delta => $value) {
-      if ($delta < $this->field['cardinality']) {
+      if ($delta < $this->field->getFieldCardinality()) {
         $this->assertEqual($entity->{$this->field_name}[$delta]->value, $value, "Value $delta is loaded correctly for current revision");
       }
       else {
@@ -140,7 +140,7 @@ function testFieldAttachLoad() {
       ));
       field_attach_load_revision($entity_type, array($eid => $entity));
       foreach ($values[$evid] as $delta => $value) {
-        if ($delta < $this->field['cardinality']) {
+        if ($delta < $this->field->getFieldCardinality()) {
           $this->assertEqual($entity->{$this->field_name}[$delta]->value, $value, "Value $delta for revision $evid is loaded correctly");
         }
         else {
@@ -180,7 +180,7 @@ function testFieldAttachInsertAndUpdate() {
     $values = array();
     // Note: we try to insert one extra value ('<=' instead of '<').
     // TODO : test empty values filtering and "compression" (store consecutive deltas).
-    for ($delta = 0; $delta <= $this->field['cardinality']; $delta++) {
+    for ($delta = 0; $delta <= $this->field->getFieldCardinality(); $delta++) {
       $values[$delta]['value'] = mt_rand(1, 127);
     }
     $entity->{$this->field_name} = $rev_values[0] = $values;
@@ -188,7 +188,7 @@ function testFieldAttachInsertAndUpdate() {
 
     $rows = db_select($this->table, 't')->fields('t')->execute()->fetchAllAssoc('delta', PDO::FETCH_ASSOC);
     foreach ($values as $delta => $value) {
-      if ($delta < $this->field['cardinality']) {
+      if ($delta < $this->field->getFieldCardinality()) {
         $this->assertEqual($rows[$delta][$this->field_name . '_value'], $value['value'], t("Value $delta is inserted correctly"));
       }
       else {
@@ -203,7 +203,7 @@ function testFieldAttachInsertAndUpdate() {
     ));
     $values = array();
     // Note: we try to update one extra value ('<=' instead of '<').
-    for ($delta = 0; $delta <= $this->field['cardinality']; $delta++) {
+    for ($delta = 0; $delta <= $this->field->getFieldCardinality(); $delta++) {
       $values[$delta]['value'] = mt_rand(1, 127);
     }
     $rev_values[1] = $values;
@@ -211,7 +211,7 @@ function testFieldAttachInsertAndUpdate() {
     field_attach_update($entity);
     $rows = db_select($this->table, 't')->fields('t')->execute()->fetchAllAssoc('delta', PDO::FETCH_ASSOC);
     foreach ($values as $delta => $value) {
-      if ($delta < $this->field['cardinality']) {
+      if ($delta < $this->field->getFieldCardinality()) {
         $this->assertEqual($rows[$delta][$this->field_name . '_value'], $value['value'], t("Value $delta is updated correctly"));
       }
       else {
@@ -531,7 +531,7 @@ function testFieldSqlStorageForeignKeys() {
     $schema = $schemas[_field_sql_storage_tablename($field)];
     $this->assertEqual(count($schema['foreign keys']), 1, 'There is 1 foreign key in the schema');
     $foreign_key = reset($schema['foreign keys']);
-    $foreign_key_column = _field_sql_storage_columnname($field['field_name'], $foreign_key_name);
+    $foreign_key_column = _field_sql_storage_columnname($field->id(), $foreign_key_name);
     $this->assertEqual($foreign_key['table'], $foreign_key_name, 'Foreign key table name preserved in the schema');
     $this->assertEqual($foreign_key['columns'][$foreign_key_column], 'id', 'Foreign key column name preserved in the schema');
   }
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php b/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php
index c900c04..0f93f17 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php
@@ -118,21 +118,21 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL,
 
     // Fields.
     foreach ($instances as $name => $instance) {
-      $field = field_info_field($instance['field_name']);
+      $field = field_info_field($instance->getFieldName());
       $admin_field_path = $this->adminPath . '/fields/' . $instance->id();
       $table[$name] = array(
         '#attributes' => array(
           'id' => drupal_html_class($name),
         ),
         'label' => array(
-          '#markup' => check_plain($instance['label']),
+          '#markup' => check_plain($instance->label()),
         ),
         'field_name' => array(
-          '#markup' => $instance['field_name'],
+          '#markup' => $instance->getFieldName(),
         ),
         'type' => array(
           '#type' => 'link',
-          '#title' => $field_types[$field['type']]['label'],
+          '#title' => $field_types[$field->getFieldType()]['label'],
           '#href' => $admin_field_path . '/field',
           '#options' => array('attributes' => array('title' => $this->t('Edit field settings.'))),
         ),
@@ -161,7 +161,7 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL,
         '#links' => $links,
       );
 
-      if (!empty($field['locked'])) {
+      if (!empty($field->locked)) {
         $table[$name]['operations'] = array('#markup' => $this->t('Locked'));
         $table[$name]['#attributes']['class'][] = 'menu-disabled';
       }
@@ -498,22 +498,22 @@ protected function getExistingFieldOptions() {
         // No need to look in the current bundle.
         if (!($existing_bundle == $this->bundle && $existing_entity_type == $this->entity_type)) {
           foreach ($instances as $instance) {
-            $field = field_info_field($instance['field_name']);
+            $field = field_info_field($instance->getFieldName());
             // Don't show
             // - locked fields,
             // - fields already in the current bundle,
             // - fields that cannot be added to the entity type,
             // - fields that should not be added via user interface.
 
-            if (empty($field['locked'])
-              && !field_info_instance($this->entity_type, $field['field_name'], $this->bundle)
-              && (empty($field['entity_types']) || in_array($this->entity_type, $field['entity_types']))
-              && empty($field_types[$field['type']]['no_ui'])) {
-              $info[$instance['field_name']] = array(
-                'type' => $field['type'],
-                'type_label' => $field_types[$field['type']]['label'],
-                'field' => $field['field_name'],
-                'label' => $instance['label'],
+            if (empty($field->locked)
+              && !field_info_instance($this->entity_type, $field->getFieldName(), $this->bundle)
+              && (empty($field->entity_types) || in_array($this->entity_type, $field->entity_types))
+              && empty($field_types[$field->getFieldType()]['no_ui'])) {
+              $info[$instance->getFieldName()] = array(
+                'type' => $field->getFieldType(),
+                'type_label' => $field_types[$field->getFieldType()]['label'],
+                'field' => $field->getFieldName(),
+                'label' => $instance->label(),
               );
             }
           }
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldDeleteForm.php b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldDeleteForm.php
index 8037ac4..0caacd1 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldDeleteForm.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldDeleteForm.php
@@ -71,7 +71,7 @@ public function submit(array $form, array &$form_state) {
     $bundles = entity_get_bundles();
     $bundle_label = $bundles[$this->entity->entity_type][$this->entity->bundle]['label'];
 
-    if ($field && !$field['locked']) {
+    if ($field && !$field->locked) {
       $this->entity->delete();
       drupal_set_message($this->t('The field %field has been deleted from the %type content type.', array('%field' => $this->entity->label(), '%type' => $bundle_label)));
     }
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldEditForm.php b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldEditForm.php
index 7e1b3bc..b631d1c 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldEditForm.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldEditForm.php
@@ -110,7 +110,7 @@ public function buildForm(array $form, array &$form_state, FieldInstanceInterfac
     }
 
     // Build the configurable field values.
-    $cardinality = $field['cardinality'];
+    $cardinality = $field->getFieldCardinality();
     $form['field']['cardinality_container'] = array(
       // We can't use the container element because it doesn't support the title
       // or description properties.
@@ -146,10 +146,10 @@ public function buildForm(array $form, array &$form_state, FieldInstanceInterfac
     );
 
     // Build the non-configurable field values.
-    $form['field']['field_name'] = array('#type' => 'value', '#value' => $field['field_name']);
-    $form['field']['type'] = array('#type' => 'value', '#value' => $field['type']);
-    $form['field']['module'] = array('#type' => 'value', '#value' => $field['module']);
-    $form['field']['active'] = array('#type' => 'value', '#value' => $field['active']);
+    $form['field']['field_name'] = array('#type' => 'value', '#value' => $field->getFieldName());
+    $form['field']['type'] = array('#type' => 'value', '#value' => $field->getFieldType());
+    $form['field']['module'] = array('#type' => 'value', '#value' => $field->module);
+    $form['field']['active'] = array('#type' => 'value', '#value' => $field->active);
 
     // Add settings provided by the field module. The field module is
     // responsible for not returning settings that cannot be changed if
@@ -159,9 +159,9 @@ public function buildForm(array $form, array &$form_state, FieldInstanceInterfac
     );
     // Create an arbitrary entity object, so that we can have an instantiated
     // FieldItem.
-    $ids = (object) array('entity_type' => $this->instance['entity_type'], 'bundle' => $this->instance['bundle'], 'entity_id' => NULL);
+    $ids = (object) array('entity_type' => $this->instance->entity_type, 'bundle' => $this->instance->bundle, 'entity_id' => NULL);
     $entity = _field_create_entity_from_ids($ids);
-    $form['field']['settings'] += $this->getFieldItem($entity, $field['field_name'])->settingsForm($form, $form_state, $field->hasData());
+    $form['field']['settings'] += $this->getFieldItem($entity, $field->getFieldName())->settingsForm($form, $form_state, $field->hasData());
 
     $form['actions'] = array('#type' => 'actions');
     $form['actions']['submit'] = array('#type' => 'submit', '#value' => $this->t('Save field settings'));
@@ -199,7 +199,7 @@ public function submitForm(array &$form, array &$form_state) {
     // Merge incoming form values into the existing field.
     $field = $this->fieldInfo->getField($field_values['field_name']);
     foreach ($field_values as $key => $value) {
-      $field[$key] = $value;
+      $field->{$key} = $value;
     }
 
     // Update the field.
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldInstanceEditForm.php b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldInstanceEditForm.php
index 4aff6da..211df95 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldInstanceEditForm.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldInstanceEditForm.php
@@ -66,8 +66,8 @@ public function getFormID() {
   public function buildForm(array $form, array &$form_state, FieldInstanceInterface $field_instance = NULL) {
     $this->instance = $form_state['instance'] = $field_instance;
 
-    $bundle = $this->instance['bundle'];
-    $entity_type = $this->instance['entity_type'];
+    $bundle = $this->instance->bundle;
+    $entity_type = $this->instance->entity_type;
     $field = $this->instance->getField();
     $bundles = entity_get_bundles();
 
@@ -78,11 +78,11 @@ public function buildForm(array $form, array &$form_state, FieldInstanceInterfac
 
     $form['#field'] = $field;
     // Create an arbitrary entity object (used by the 'default value' widget).
-    $ids = (object) array('entity_type' => $this->instance['entity_type'], 'bundle' => $this->instance['bundle'], 'entity_id' => NULL);
+    $ids = (object) array('entity_type' => $this->instance->entity_type, 'bundle' => $this->instance->bundle, 'entity_id' => NULL);
     $form['#entity'] = _field_create_entity_from_ids($ids);
     $items = $this->getFieldItems($form['#entity'], $this->instance['field_name']);
 
-    if (!empty($field['locked'])) {
+    if (!empty($field->locked)) {
       $form['locked'] = array(
         '#markup' => $this->t('The field %field is locked and cannot be edited.', array('%field' => $this->instance->label())),
       );
@@ -97,7 +97,7 @@ public function buildForm(array $form, array &$form_state, FieldInstanceInterfac
     // Build the non-configurable instance values.
     $form['instance']['field_name'] = array(
       '#type' => 'value',
-      '#value' => $this->instance['field_name'],
+      '#value' => $this->instance->getFieldName(),
     );
     $form['instance']['entity_type'] = array(
       '#type' => 'value',
@@ -112,7 +112,7 @@ public function buildForm(array $form, array &$form_state, FieldInstanceInterfac
     $form['instance']['label'] = array(
       '#type' => 'textfield',
       '#title' => $this->t('Label'),
-      '#default_value' => $this->instance->label() ?: $field['field_name'],
+      '#default_value' => $this->instance->label() ?: $field->getFieldName(),
       '#required' => TRUE,
       '#weight' => -20,
     );
@@ -120,7 +120,7 @@ public function buildForm(array $form, array &$form_state, FieldInstanceInterfac
     $form['instance']['description'] = array(
       '#type' => 'textarea',
       '#title' => $this->t('Help text'),
-      '#default_value' => !empty($this->instance['description']) ? $this->instance['description'] : '',
+      '#default_value' => !empty($this->instance->description) ? $this->instance->description : '',
       '#rows' => 5,
       '#description' => $this->t('Instructions to present to the user below this field on the editing form.<br />Allowed HTML tags: @tags', array('@tags' => _field_filter_xss_display_allowed_tags())) . '<br />' . $this->t('This field supports tokens.'),
       '#weight' => -10,
@@ -129,7 +129,7 @@ public function buildForm(array $form, array &$form_state, FieldInstanceInterfac
     $form['instance']['required'] = array(
       '#type' => 'checkbox',
       '#title' => $this->t('Required field'),
-      '#default_value' => !empty($this->instance['required']),
+      '#default_value' => !empty($this->instance->required),
       '#weight' => -5,
     );
 
@@ -165,7 +165,7 @@ public function buildForm(array $form, array &$form_state, FieldInstanceInterfac
    */
   public function validateForm(array &$form, array &$form_state) {
     if (isset($form['instance']['default_value'])) {
-      $items = $this->getFieldItems($form['#entity'], $this->instance['field_name']);
+      $items = $this->getFieldItems($form['#entity'], $this->instance->getFieldName());
       $items->defaultValuesFormValidate($form['instance']['default_value'], $form, $form_state);
     }
   }
@@ -184,7 +184,7 @@ public function submitForm(array &$form, array &$form_state) {
 
     // Merge incoming values into the instance.
     foreach ($form_state['values']['instance'] as $key => $value) {
-      $this->instance[$key] = $value;
+      $this->instance->$key = $value;
     }
     $this->instance->save();
 
@@ -202,7 +202,7 @@ public function delete(array &$form, array &$form_state) {
       $destination = drupal_get_destination();
       unset($_GET['destination']);
     }
-    $form_state['redirect'] = array('admin/structure/types/manage/' . $this->instance['bundle'] . '/fields/' . $this->instance->id() . '/delete', array('query' => $destination));
+    $form_state['redirect'] = array('admin/structure/types/manage/' . $this->instance->bundle . '/fields/' . $this->instance->id() . '/delete', array('query' => $destination));
   }
 
   /**
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldWidgetTypeForm.php b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldWidgetTypeForm.php
new file mode 100644
index 0000000..f257c56
--- /dev/null
+++ b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldWidgetTypeForm.php
@@ -0,0 +1,99 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\field_ui\Form\FieldWidgetTypeForm.
+ */
+
+namespace Drupal\field_ui\Form;
+
+use Drupal\field\FieldInstanceInterface;
+
+/**
+ * Provides a form for the widget selection form.
+ */
+class FieldWidgetTypeForm extends FieldInstanceFormBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormID() {
+    return 'field_ui_widget_type_form';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, array &$form_state, FieldInstanceInterface $field_instance = NULL) {
+    parent::buildForm($form, $form_state, $field_instance);
+
+    drupal_set_title($this->instance->label());
+
+    $bundle = $this->instance->bundle;
+    $entity_type = $this->instance->entity_type;
+    $field_name = $this->instance->getFieldName();
+
+    $entity_form_display = entity_get_form_display($entity_type, $bundle, 'default');
+    $field = $this->instance->getField();
+    $bundles = entity_get_bundles();
+    $bundle_label = $bundles[$entity_type][$bundle]['label'];
+
+    $form = array(
+      '#bundle' => $bundle,
+      '#entity_type' => $entity_type,
+      '#field_name' => $field_name,
+      '#instance' => $this->instance,
+    );
+
+    $form['widget_type'] = array(
+      '#type' => 'select',
+      '#title' => t('Widget type'),
+      '#required' => TRUE,
+      '#options' => $this->widgetManager->getOptions($field->type),
+      '#default_value' => $entity_form_display->getWidget($field_name)->getPluginId(),
+      '#description' => t('The type of form element you would like to present to the user when creating this field in the %type type.', array('%type' => $bundle_label)),
+    );
+
+    $form['actions'] = array('#type' => 'actions');
+    $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Continue'));
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validateForm(array &$form, array &$form_state) {
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, array &$form_state) {
+    $form_values = $form_state['values'];
+    $bundle = $form['#bundle'];
+    $entity_type = $form['#entity_type'];
+    $field_name = $form['#field_name'];
+    $instance = $form['#instance'];
+
+    $entity_form_display = entity_get_form_display($entity_type, $bundle, 'default')
+      ->setComponent($field_name, array(
+        'type' => $form_values['widget_type'],
+      ));
+
+    try {
+      $entity_form_display->save();
+      drupal_set_message(t('Changed the widget for field %label.', array('%label' => $instance->label())));
+
+      /*if ($instance->required && empty($instance->default_value) && empty($instance->default_value_function) && $instance['widget']['type'] == 'field_hidden') {
+        drupal_set_message(t('Field %label is required and uses the "hidden" widget. You might want to configure a default value.', array('%label' => $instance->label())), 'warning');
+      }*/
+    }
+    catch (\Exception $e) {
+      drupal_set_message(t('There was a problem changing the widget for field %label.', array('%label' => $instance->label())), 'error');
+    }
+
+    $form_state['redirect'] = $this->getNextDestination();
+  }
+
+}
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageDisplayTest.php b/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageDisplayTest.php
index d1edd6d..eb81c88 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageDisplayTest.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageDisplayTest.php
@@ -243,10 +243,6 @@ function testNonInitializedFields() {
     );
     $this->fieldUIAddNewField('admin/structure/types/manage/' . $this->type, $edit);
 
-    // Check that no settings have been set for the 'teaser' mode.
-    $instance = field_info_instance('node', 'field_test', $this->type);
-    $this->assertFalse(isset($instance['display']['teaser']));
-
     // Check that the field appears as 'hidden' on the 'Manage display' page
     // for the 'teaser' mode.
     $this->drupalGet('admin/structure/types/manage/' . $this->type . '/display/teaser');
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageFieldsTest.php b/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageFieldsTest.php
index 8f29e45..0794b90 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageFieldsTest.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageFieldsTest.php
@@ -232,11 +232,11 @@ function assertFieldSettings($bundle, $field_name, $string = 'dummy test string'
     field_info_cache_clear();
     // Assert field settings.
     $field = field_info_field($field_name);
-    $this->assertTrue($field['settings']['test_field_setting'] == $string, 'Field settings were found.');
+    $this->assertTrue($field->settings['test_field_setting'] == $string, 'Field settings were found.');
 
     // Assert instance settings.
     $instance = field_info_instance($entity_type, $field_name, $bundle);
-    $this->assertTrue($instance['settings']['test_instance_setting'] == $string, 'Field instance settings were found.');
+    $this->assertTrue($instance->settings['test_instance_setting'] == $string, 'Field instance settings were found.');
   }
 
   /**
@@ -308,7 +308,7 @@ function testDefaultValue() {
     $this->assertText("Saved $field_name configuration", 'The form was successfully submitted.');
     field_info_cache_clear();
     $instance = field_info_instance('node', $field_name, $this->type);
-    $this->assertEqual($instance['default_value'], array(array('value' => 1)), 'The default value was correctly saved.');
+    $this->assertEqual($instance->default_value, array(array('value' => 1)), 'The default value was correctly saved.');
 
     // Check that the default value shows up in the form
     $this->drupalGet($admin_path);
@@ -320,10 +320,10 @@ function testDefaultValue() {
     $this->assertText("Saved $field_name configuration", 'The form was successfully submitted.');
     field_info_cache_clear();
     $instance = field_info_instance('node', $field_name, $this->type);
-    $this->assertEqual($instance['default_value'], NULL, 'The default value was correctly saved.');
+    $this->assertEqual($instance->default_value, NULL, 'The default value was correctly saved.');
 
     // Check that the default widget is used when the field is hidden.
-    entity_get_form_display($instance['entity_type'], $instance['bundle'], 'default')
+    entity_get_form_display($instance->entity_type, $instance->bundle, 'default')
       ->removeComponent($field_name)->save();
     $this->drupalGet($admin_path);
     $this->assertFieldById($element_id, '', 'The default value widget was displayed when field is hidden.');
diff --git a/core/modules/file/file.field.inc b/core/modules/file/file.field.inc
index 7acd885..6ab4a4c 100644
--- a/core/modules/file/file.field.inc
+++ b/core/modules/file/file.field.inc
@@ -7,6 +7,7 @@
 
 use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\field\FieldInterface;
 
 /**
  * Implements hook_field_info().
@@ -39,8 +40,8 @@ function file_field_info() {
  * Implements hook_field_settings_form().
  */
 function file_field_settings_form($field, $instance) {
-  $defaults = \Drupal::service('plugin.manager.entity.field.field_type')->getDefaultSettings($field['type']);
-  $settings = array_merge($defaults, $field['settings']);
+  $defaults = \Drupal::service('plugin.manager.entity.field.field_type')->getDefaultSettings($field->getFieldType());
+  $settings = array_merge($defaults, $field->settings);
 
   $form['#attached']['library'][] = array('file', 'drupal.file');
 
@@ -82,7 +83,7 @@ function file_field_settings_form($field, $instance) {
  * Implements hook_field_instance_settings_form().
  */
 function file_field_instance_settings_form($field, $instance) {
-  $settings = $instance['settings'];
+  $settings = $instance->settings;
 
   $form['file_directory'] = array(
     '#type' => 'textfield',
@@ -218,8 +219,8 @@ function file_field_update(EntityInterface $entity, $field, $instance, $langcode
   // Compare the original field values with the ones that are being saved.
   $original = $entity->original->getBCEntity();
   $original_fids = array();
-  if (!empty($original->{$field['field_name']}[$langcode])) {
-    foreach ($original->{$field['field_name']}[$langcode] as $original_item) {
+  if (!empty($original->{$field->getFieldName()}[$langcode])) {
+    foreach ($original->{$field->getFieldName()}[$langcode] as $original_item) {
       $original_fids[] = $original_item['target_id'];
       if (isset($original_item['target_id']) && !in_array($original_item['target_id'], $current_fids)) {
         // Decrement the file usage count by 1.
@@ -359,8 +360,8 @@ function file_field_widget_multiple_count_validate($element, &$form_state, $form
   $field = field_info_field($element['#field_name']);
   $uploaded = count($values['fids']);
   $count = $uploaded + $current;
-  if ($count > $field['cardinality']) {
-    $keep = $uploaded - $count + $field['cardinality'];
+  if ($count > $field->getFieldCardinality()) {
+    $keep = $uploaded - $count + $field->getFieldCardinality();
     $removed_files = array_slice($values['fids'], $keep);
     $removed_names = array();
     foreach ($removed_files as $fid) {
@@ -371,8 +372,8 @@ function file_field_widget_multiple_count_validate($element, &$form_state, $form
       t(
         'Field %field can only hold @max values but there were @count uploaded. The following files have been omitted as a result: %list.',
         array(
-          '%field' => $field['field_name'],
-          '@max' => $field['cardinality'],
+          '%field' => $field->getFieldName(),
+          '@max' => $field->getFieldCardinality(),
           '@count' => $keep,
           '%list' => implode(', ', $removed_names),
         )
@@ -792,8 +793,9 @@ function theme_file_upload_help($variables) {
  *   The field column if the field references {file_managed}.fid, typically
  *   fid, FALSE if it doesn't.
  */
-function file_field_find_file_reference_column($field) {
-  foreach ($field['foreign keys'] as $data) {
+function file_field_find_file_reference_column(FieldInterface $field) {
+  $schema = $field->getSchema();
+  foreach ($schema['foreign keys'] as $data) {
     if ($data['table'] == 'file_managed') {
       foreach ($data['columns'] as $field_column => $column) {
         if ($column == 'fid') {
diff --git a/core/modules/file/file.module b/core/modules/file/file.module
index e59126d..c1d6d63 100644
--- a/core/modules/file/file.module
+++ b/core/modules/file/file.module
@@ -1870,12 +1870,12 @@ function file_get_file_references(File $file, $field = NULL, $age = FIELD_LOAD_R
             $current_field = field_info_field($field_name);
             // If this is the first time this field type is seen, check
             // whether it references files.
-            if (!isset($field_columns[$current_field['type']])) {
-              $field_columns[$current_field['type']] = file_field_find_file_reference_column($current_field);
+            if (!isset($field_columns[$current_field->type])) {
+              $field_columns[$current_field->type] = file_field_find_file_reference_column($current_field);
             }
             // If the field type does reference files then record it.
-            if ($field_columns[$current_field['type']]) {
-              $file_fields[$entity_type][$bundle][$field_name] = $field_columns[$current_field['type']];
+            if ($field_columns[$current_field->type]) {
+              $file_fields[$entity_type][$bundle][$field_name] = $field_columns[$current_field->type];
             }
           }
         }
@@ -1906,7 +1906,7 @@ function file_get_file_references(File $file, $field = NULL, $age = FIELD_LOAD_R
   if ($field || $field_type) {
     foreach ($return as $field_name => $data) {
       $current_field = field_info_field($field_name);
-      if (($field_type && $current_field['type'] != $field_type) || ($field && $field['id'] != $current_field['id'])) {
+      if (($field_type && $current_field->type != $field_type) || ($field && $field->id() != $current_field->id)) {
         unset($return[$field_name]);
       }
     }
diff --git a/core/modules/file/file.views.inc b/core/modules/file/file.views.inc
index db18c46..a58bb3d 100644
--- a/core/modules/file/file.views.inc
+++ b/core/modules/file/file.views.inc
@@ -464,12 +464,12 @@ function file_field_views_data($field) {
   $data = field_views_field_default_views_data($field);
   foreach ($data as $table_name => $table_data) {
     // Add the relationship only on the fid field.
-    $data[$table_name][$field['field_name'] . '_target_id']['relationship'] = array(
+    $data[$table_name][$field->id() . '_target_id']['relationship'] = array(
       'id' => 'standard',
       'base' => 'file_managed',
       'entity type' => 'file',
-      'base field' => 'target_id',
-      'label' => t('file from !field_name', array('!field_name' => $field['field_name'])),
+      'base field' => 'fid',
+      'label' => t('file from !field_name', array('!field_name' => $field->id())),
     );
   }
 
@@ -482,11 +482,11 @@ function file_field_views_data($field) {
  * Views integration to provide reverse relationships on file fields.
  */
 function file_field_views_data_views_data_alter(&$data, $field) {
-  foreach ($field['bundles'] as $entity_type => $bundles) {
+  foreach ($field->getBundles() as $entity_type => $bundles) {
     $entity_info = entity_get_info($entity_type);
-    $pseudo_field_name = 'reverse_' . $field['field_name'] . '_' . $entity_type;
+    $pseudo_field_name = 'reverse_' . $field->id() . '_' . $entity_type;
 
-    list($label, $all_labels) = field_views_field_label($field['field_name']);
+    list($label, $all_labels) = field_views_field_label($field->id());
     $entity = $entity_info['label'];
     if ($entity == t('Node')) {
       $entity = t('Content');
@@ -496,12 +496,12 @@ function file_field_views_data_views_data_alter(&$data, $field) {
       'title' => t('@entity using @field', array('@entity' => $entity, '@field' => $label)),
       'help' => t('Relate each @entity with a @field set to the file.', array('@entity' => $entity, '@field' => $label)),
       'id' => 'entity_reverse',
-      'field_name' => $field['field_name'],
+      'field_name' => $field->id(),
       'field table' => _field_sql_storage_tablename($field),
-      'field field' => $field['field_name'] . '_target_id',
+      'field field' => $field->id() . '_target_id',
       'base' => $entity_info['base_table'],
       'base field' => $entity_info['entity_keys']['id'],
-      'label' => t('!field_name', array('!field_name' => $field['field_name'])),
+      'label' => t('!field_name', array('!field_name' => $field->id())),
       'join_extra' => array(
         0 => array(
           'field' => 'entity_type',
diff --git a/core/modules/file/lib/Drupal/file/Tests/FileFieldTestBase.php b/core/modules/file/lib/Drupal/file/Tests/FileFieldTestBase.php
index ba51a17..36cd46a 100644
--- a/core/modules/file/lib/Drupal/file/Tests/FileFieldTestBase.php
+++ b/core/modules/file/lib/Drupal/file/Tests/FileFieldTestBase.php
@@ -98,7 +98,7 @@ function createFileField($name, $type_name, $field_settings = array(), $instance
    *   A list of widget settings that will be added to the widget defaults.
    */
   function attachFileField($name, $entity_type, $bundle, $instance_settings = array(), $widget_settings = array()) {
-    $instance = array(
+    $instance_definition = array(
       'field_name' => $name,
       'label' => $name,
       'entity_type' => $entity_type,
@@ -106,8 +106,8 @@ function attachFileField($name, $entity_type, $bundle, $instance_settings = arra
       'required' => !empty($instance_settings['required']),
       'settings' => array(),
     );
-    $instance['settings'] = array_merge($instance['settings'], $instance_settings);
-    entity_create('field_instance', $instance)->save();
+    $instance_definition['settings'] = array_merge($instance_definition['settings'], $instance_settings);
+    entity_create('field_instance', $instance_definition)->save();
 
     entity_get_form_display($entity_type, $bundle, 'default')
       ->setComponent($name, array(
@@ -122,12 +122,12 @@ function attachFileField($name, $entity_type, $bundle, $instance_settings = arra
    */
   function updateFileField($name, $type_name, $instance_settings = array(), $widget_settings = array()) {
     $instance = field_info_instance('node', $name, $type_name);
-    $instance['settings'] = array_merge($instance['settings'], $instance_settings);
+    $instance->settings = array_merge($instance->settings, $instance_settings);
 
     $instance->save();
 
-    entity_get_form_display($instance['entity_type'], $instance['bundle'], 'default')
-      ->setComponent($instance['field_name'], array(
+    entity_get_form_display($instance->entity_type, $instance->bundle, 'default')
+      ->setComponent($instance->getFieldName(), array(
         'settings' => $widget_settings,
       ))
       ->save();
@@ -161,7 +161,7 @@ function uploadNodeFile($file, $field_name, $nid_or_type, $new_revision = TRUE,
     // Attach a file to the node.
     $field = field_info_field($field_name);
     $name = 'files[' . $field_name . '_' . $langcode . '_0]';
-    if ($field['cardinality'] != 1) {
+    if ($field->cardinality != 1) {
       $name .= '[]';
     }
     $edit[$name] = drupal_realpath($file->getFileUri());
diff --git a/core/modules/file/lib/Drupal/file/Tests/FileFieldValidateTest.php b/core/modules/file/lib/Drupal/file/Tests/FileFieldValidateTest.php
index 46d8cbf..9e4e1f2 100644
--- a/core/modules/file/lib/Drupal/file/Tests/FileFieldValidateTest.php
+++ b/core/modules/file/lib/Drupal/file/Tests/FileFieldValidateTest.php
@@ -38,7 +38,7 @@ function testRequired() {
     // Try to post a new node without uploading a file.
     $edit = array("title" => $this->randomName());
     $this->drupalPost('node/add/' . $type_name, $edit, t('Save and publish'));
-    $this->assertRaw(t('!title field is required.', array('!title' => $instance['label'])), 'Node save failed when required file field was empty.');
+    $this->assertRaw(t('!title field is required.', array('!title' => $instance->label)), 'Node save failed when required file field was empty.');
 
     // Create a new node with the uploaded file.
     $nid = $this->uploadNodeFile($test_file, $field_name, $type_name);
@@ -57,7 +57,7 @@ function testRequired() {
     // Try to post a new node without uploading a file in the multivalue field.
     $edit = array('title' => $this->randomName());
     $this->drupalPost('node/add/' . $type_name, $edit, t('Save and publish'));
-    $this->assertRaw(t('!title field is required.', array('!title' => $instance['label'])), 'Node save failed when required multiple value file field was empty.');
+    $this->assertRaw(t('!title field is required.', array('!title' => $instance->label)), 'Node save failed when required multiple value file field was empty.');
 
     // Create a new node with the uploaded file into the multivalue field.
     $nid = $this->uploadNodeFile($test_file, $field_name, $type_name);
diff --git a/core/modules/file/tests/file_module_test.module b/core/modules/file/tests/file_module_test.module
index fc116ad..6e172d0 100644
--- a/core/modules/file/tests/file_module_test.module
+++ b/core/modules/file/tests/file_module_test.module
@@ -88,7 +88,7 @@ function file_module_test_form_submit($form, &$form_state) {
  * Implements hook_file_download_access().
  */
 function file_module_test_file_download_access($field, EntityInterface $entity, File $file) {
-  $instance = field_info_instance($entity->entityType(), $field['field_name'], $entity->bundle());
+  $instance = field_info_instance($entity->entityType(), $field->id(), $entity->bundle());
   // Allow the file to be downloaded only if the given arguments are correct.
   // If any are wrong, $instance will be NULL.
   if (empty($instance)) {
diff --git a/core/modules/forum/forum.module b/core/modules/forum/forum.module
index e8c104f..e019e80 100644
--- a/core/modules/forum/forum.module
+++ b/core/modules/forum/forum.module
@@ -174,7 +174,7 @@ function forum_menu_local_tasks(&$data, $router_item, $root_path) {
       $links = array();
       // Loop through all bundles for forum taxonomy vocabulary field.
       $field = field_info_field('taxonomy_forums');
-      foreach ($field['bundles']['node'] as $type_name) {
+      foreach ($field->getBundles('node') as $type_name) {
         if (($type = entity_load('node_type', $type_name)) && node_access('create', $type_name)) {
           $links[$type_name] = array(
             '#theme' => 'menu_local_action',
diff --git a/core/modules/image/image.field.inc b/core/modules/image/image.field.inc
index c682747..2e3a574 100644
--- a/core/modules/image/image.field.inc
+++ b/core/modules/image/image.field.inc
@@ -58,8 +58,8 @@ function image_field_info() {
  * Implements hook_field_settings_form().
  */
 function image_field_settings_form($field, $instance) {
-  $defaults = \Drupal::service('plugin.manager.entity.field.field_type')->getDefaultSettings($field['type']);
-  $settings = array_merge($defaults, $field['settings']);
+  $defaults = \Drupal::service('plugin.manager.entity.field.field_type')->getDefaultSettings($field->getFieldtype());
+  $settings = array_merge($defaults, $field->settings);
 
   $scheme_options = array();
   foreach (file_get_stream_wrappers(STREAM_WRAPPERS_WRITE_VISIBLE) as $scheme => $stream_wrapper) {
@@ -80,7 +80,7 @@ function image_field_settings_form($field, $instance) {
     '#title' => t('Default image'),
     '#type' => 'managed_file',
     '#description' => t('If no image is uploaded, this image will be shown on display.'),
-    '#default_value' => empty($field['settings']['default_image']) ? array() : array($field['settings']['default_image']),
+    '#default_value' => empty($field->settings['default_image']) ? array() : array($field->settings['default_image']),
     '#upload_location' => $settings['uri_scheme'] . '://default_images/',
   );
 
@@ -91,7 +91,7 @@ function image_field_settings_form($field, $instance) {
  * Implements hook_field_instance_settings_form().
  */
 function image_field_instance_settings_form($field, $instance) {
-  $settings = $instance['settings'];
+  $settings = $instance->settings;
 
   // Use the file field instance settings form as a basis.
   $form = file_field_instance_settings_form($field, $instance);
@@ -199,7 +199,7 @@ function image_field_instance_settings_form($field, $instance) {
     '#type' => 'managed_file',
     '#description' => t("If no image is uploaded, this image will be shown on display and will override the field's default image."),
     '#default_value' => empty($settings['default_image']) ? array() : array($settings['default_image']),
-    '#upload_location' => $field['settings']['uri_scheme'] . '://default_images/',
+    '#upload_location' => $field->settings['uri_scheme'] . '://default_images/',
   );
 
   return $form;
diff --git a/core/modules/image/image.views.inc b/core/modules/image/image.views.inc
index 2e70c08..336e2cd 100644
--- a/core/modules/image/image.views.inc
+++ b/core/modules/image/image.views.inc
@@ -18,12 +18,12 @@
 function image_field_views_data($field) {
   $data = field_views_field_default_views_data($field);
   foreach ($data as $table_name => $table_data) {
-    // Add the relationship only on the target_id field.
-    $data[$table_name][$field['field_name'] . '_target_id']['relationship'] = array(
+    // Add the relationship only on the fid field.
+    $data[$table_name][$field->id() . '_fid']['relationship'] = array(
       'id' => 'standard',
       'base' => 'file_managed',
-      'base field' => 'target_id',
-      'label' => t('image from !field_name', array('!field_name' => $field['field_name'])),
+      'base field' => 'fid',
+      'label' => t('image from !field_name', array('!field_name' => $field->id())),
     );
   }
 
@@ -36,11 +36,11 @@ function image_field_views_data($field) {
  * Views integration to provide reverse relationships on image fields.
  */
 function image_field_views_data_views_data_alter(&$data, $field) {
-  foreach ($field['bundles'] as $entity_type => $bundles) {
+  foreach ($field->getBundles() as $entity_type => $bundles) {
     $entity_info = entity_get_info($entity_type);
-    $pseudo_field_name = 'reverse_' . $field['field_name'] . '_' . $entity_type;
+    $pseudo_field_name = 'reverse_' . $field->id() . '_' . $entity_type;
 
-    list($label, $all_labels) = field_views_field_label($field['field_name']);
+    list($label, $all_labels) = field_views_field_label($field->id());
     $entity = $entity_info['label'];
     if ($entity == t('Node')) {
       $entity = t('Content');
@@ -50,12 +50,12 @@ function image_field_views_data_views_data_alter(&$data, $field) {
       'title' => t('@entity using @field', array('@entity' => $entity, '@field' => $label)),
       'help' => t('Relate each @entity with a @field set to the image.', array('@entity' => $entity, '@field' => $label)),
       'id' => 'entity_reverse',
-      'field_name' => $field['field_name'],
+      'field_name' => $field->id(),
       'field table' => _field_sql_storage_tablename($field),
-      'field field' => $field['field_name'] . '_target_id',
+      'field field' => $field->id() . '_target_id',
       'base' => $entity_info['base_table'],
       'base field' => $entity_info['entity_keys']['id'],
-      'label' => t('!field_name', array('!field_name' => $field['field_name'])),
+      'label' => t('!field_name', array('!field_name' => $field->id())),
       'join_extra' => array(
         0 => array(
           'field' => 'entity_type',
diff --git a/core/modules/image/lib/Drupal/image/Entity/ImageStyle.php b/core/modules/image/lib/Drupal/image/Entity/ImageStyle.php
index 4d12539..a2ea695 100644
--- a/core/modules/image/lib/Drupal/image/Entity/ImageStyle.php
+++ b/core/modules/image/lib/Drupal/image/Entity/ImageStyle.php
@@ -143,26 +143,26 @@ protected static function replaceImageStyle(ImageStyleInterface $style) {
       // Loop through all fields searching for image fields.
       foreach ($instances as $instance) {
         if ($instance->getField()->type == 'image') {
-          $view_modes = entity_get_view_modes($instance['entity_type']);
+          $view_modes = entity_get_view_modes($instance->entity_type);
           $view_modes = array('default') + array_keys($view_modes);
           foreach ($view_modes as $view_mode) {
-            $display = entity_get_display($instance['entity_type'], $instance['bundle'], $view_mode);
-            $display_options = $display->getComponent($instance['field_name']);
+            $display = entity_get_display($instance->entity_type, $instance->bundle, $view_mode);
+            $display_options = $display->getComponent($instance->getFieldName());
 
             // Check if the formatter involves an image style.
             if ($display_options && $display_options['type'] == 'image' && $display_options['settings']['image_style'] == $style->getOriginalID()) {
               // Update display information for any instance using the image
               // style that was just deleted.
               $display_options['settings']['image_style'] = $style->id();
-              $display->setComponent($instance['field_name'], $display_options)
+              $display->setComponent($instance->getFieldName(), $display_options)
                 ->save();
             }
           }
-          $entity_form_display = entity_get_form_display($instance['entity_type'], $instance['bundle'], 'default');
-          $widget_configuration = $entity_form_display->getComponent($instance['field_name']);
+          $entity_form_display = entity_get_form_display($instance->entity_type, $instance->bundle, 'default');
+          $widget_configuration = $entity_form_display->getComponent($instance->getFieldName());
           if ($widget_configuration['settings']['preview_image_style'] == $style->getOriginalID()) {
             $widget_options['settings']['preview_image_style'] = $style->id();
-            $entity_form_display->setComponent($instance['field_name'], $widget_options)
+            $entity_form_display->setComponent($instance->getFieldName(), $widget_options)
               ->save();
           }
         }
diff --git a/core/modules/image/lib/Drupal/image/Plugin/field/formatter/ImageFormatterBase.php b/core/modules/image/lib/Drupal/image/Plugin/field/formatter/ImageFormatterBase.php
index 0ed0be4..42078a2 100644
--- a/core/modules/image/lib/Drupal/image/Plugin/field/formatter/ImageFormatterBase.php
+++ b/core/modules/image/lib/Drupal/image/Plugin/field/formatter/ImageFormatterBase.php
@@ -26,8 +26,8 @@ public function prepareView(array $entities, $langcode, array $items) {
         $fid = array();
         $instance = field_info_instance($entity->entityType(), $this->fieldDefinition->getFieldName(), $entity->bundle());
         // Use the default for the instance if one is available.
-        if (!empty($instance['settings']['default_image'])) {
-          $fid = array($instance['settings']['default_image']);
+        if (!empty($instance->settings['default_image'])) {
+          $fid = array($instance->settings['default_image']);
         }
         // Otherwise, use the default for the field.
         // Note, that we have to bypass getFieldSetting() as this returns the
diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDefaultImagesTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDefaultImagesTest.php
index f926abc..95a33a6 100644
--- a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDefaultImagesTest.php
+++ b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDefaultImagesTest.php
@@ -82,7 +82,7 @@ public function testDefaultImages() {
     ));
     $instance2->save();
 
-    $widget_settings = entity_get_form_display($instance['entity_type'], $instance['bundle'], 'default')->getComponent($field['field_name']);
+    $widget_settings = entity_get_form_display($instance->entity_type, $instance->bundle, 'default')->getComponent($field->id());
     entity_get_form_display('node', 'page', 'default')
       ->setComponent($field->id(), $widget_settings)
       ->save();
@@ -157,7 +157,7 @@ public function testDefaultImages() {
     );
 
     // Upload a new default for the field.
-    $field['settings']['default_image'] = array($default_images['field_new']->id());
+    $field->settings['default_image'] = array($default_images['field_new']->id());
     $field->save();
 
     // Confirm that the new default is used on the article field settings form.
@@ -192,7 +192,7 @@ public function testDefaultImages() {
     );
 
     // Upload a new default for the article's field instance.
-    $instance['settings']['default_image'] = $default_images['instance_new']->id();
+    $instance->settings['default_image'] = $default_images['instance_new']->id();
     $instance->save();
 
     // Confirm the new field instance default is used on the article field
@@ -231,7 +231,7 @@ public function testDefaultImages() {
     );
 
     // Remove the instance default from articles.
-    $instance['settings']['default_image'] = 0;
+    $instance->settings['default_image'] = 0;
     $instance->save();
 
     // Confirm the article field instance default has been removed.
diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php
index b7d1b15..5438c4d 100644
--- a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php
+++ b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php
@@ -250,7 +250,7 @@ function testImageFieldDefaultImage() {
     // Clear field info cache so the new default image is detected.
     field_info_cache_clear();
     $field = field_info_field($field_name);
-    $file = file_load($field['settings']['default_image']);
+    $file = file_load($field->settings['default_image']);
     $this->assertTrue($file->isPermanent(), 'The default image status is permanent.');
     $image = array(
       '#theme' => 'image',
@@ -283,7 +283,7 @@ function testImageFieldDefaultImage() {
     // Clear field info cache so the new default image is detected.
     field_info_cache_clear();
     $field = field_info_field($field_name);
-    $this->assertFalse($field['settings']['default_image'], 'Default image removed from field.');
+    $this->assertFalse($field->settings['default_image'], 'Default image removed from field.');
     // Create an image field that uses the private:// scheme and test that the
     // default image works as expected.
     $private_field_name = strtolower($this->randomName());
diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageFieldTestBase.php b/core/modules/image/lib/Drupal/image/Tests/ImageFieldTestBase.php
index 7d0f054..3e72520 100644
--- a/core/modules/image/lib/Drupal/image/Tests/ImageFieldTestBase.php
+++ b/core/modules/image/lib/Drupal/image/Tests/ImageFieldTestBase.php
@@ -65,17 +65,19 @@ function setUp() {
    *   A list of widget settings that will be added to the widget defaults.
    */
   function createImageField($name, $type_name, $field_settings = array(), $instance_settings = array(), $widget_settings = array()) {
-    $field = array(
+    $field_definition = array(
       'field_name' => $name,
       'type' => 'image',
       'settings' => array(),
       'cardinality' => !empty($field_settings['cardinality']) ? $field_settings['cardinality'] : 1,
     );
-    $field['settings'] = array_merge($field['settings'], $field_settings);
-    entity_create('field_entity', $field)->save();
+    $field_definition['settings'] = array_merge($field_definition['settings'], $field_settings);
 
-    $instance = array(
-      'field_name' => $field['field_name'],
+    $field = entity_create('field_entity', $field_definition);
+    $field->save();
+
+    $instance_definition = array(
+      'field_name' => $field->id(),
       'entity_type' => 'node',
       'label' => $name,
       'bundle' => $type_name,
@@ -83,19 +85,19 @@ function createImageField($name, $type_name, $field_settings = array(), $instanc
       'description' => !empty($instance_settings['description']) ? $instance_settings['description'] : '',
       'settings' => array(),
     );
-    $instance['settings'] = array_merge($instance['settings'], $instance_settings);
-    $field_instance = entity_create('field_instance', $instance);
+    $instance_definition['settings'] = array_merge($instance_definition['settings'], $instance_settings);
+    $field_instance = entity_create('field_instance', $instance_definition);
     $field_instance->save();
 
     entity_get_form_display('node', $type_name, 'default')
-      ->setComponent($field['field_name'], array(
+      ->setComponent($field->id(), array(
         'type' => 'image_image',
         'settings' => $widget_settings,
       ))
       ->save();
 
     entity_get_display('node', $type_name, 'default')
-      ->setComponent($field['field_name'])
+      ->setComponent($field->id())
       ->save();
 
     return $field_instance;
diff --git a/core/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php b/core/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php
index c3c62ef..9dff86b 100644
--- a/core/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php
+++ b/core/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php
@@ -465,7 +465,7 @@ function testLinkSeparateFormatter() {
         // Update the field formatter settings.
         $display_options['settings'] = array($setting => $new_value);
         entity_get_display('entity_test', 'entity_test', 'full')
-          ->setComponent($this->field['field_name'], $display_options)
+          ->setComponent($this->field->id(), $display_options)
           ->save();
 
         $this->renderTestEntity($id);
diff --git a/core/modules/node/lib/Drupal/node/Plugin/views/wizard/Node.php b/core/modules/node/lib/Drupal/node/Plugin/views/wizard/Node.php
index 33edd5d..0fc5273 100644
--- a/core/modules/node/lib/Drupal/node/Plugin/views/wizard/Node.php
+++ b/core/modules/node/lib/Drupal/node/Plugin/views/wizard/Node.php
@@ -279,11 +279,11 @@ protected function buildFilters(&$form, &$form_state) {
     $tag_fields = array();
     foreach ($bundles as $bundle) {
       foreach (field_info_instances($this->entity_type, $bundle) as $instance) {
-        $widget = entity_get_form_display($instance['entity_type'], $instance['bundle'], 'default')->getComponent($instance['field_name']);
+        $widget = entity_get_form_display($instance->entity_type, $instance->bundle, 'default')->getComponent($instance->getFieldName());
         // We define "tag-like" taxonomy fields as ones that use the
         // "Autocomplete term widget (tagging)" widget.
         if ($widget['type'] == 'taxonomy_autocomplete') {
-          $tag_fields[] = $instance['field_name'];
+          $tag_fields[] = $instance->getFieldName();
         }
       }
     }
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeTokenReplaceTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeTokenReplaceTest.php
index 1e55f29..05bdff8 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeTokenReplaceTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeTokenReplaceTest.php
@@ -54,8 +54,8 @@ function testNodeTokenReplacement() {
     $tests['[node:type]'] = 'article';
     $tests['[node:type-name]'] = 'Article';
     $tests['[node:title]'] = check_plain($node->getTitle());
-    $tests['[node:body]'] = text_sanitize($instance['settings']['text_processing'], $node->language()->id, $node->body[0]->getValue(), 'value');
-    $tests['[node:summary]'] = text_sanitize($instance['settings']['text_processing'], $node->language()->id, $node->body[0]->getValue(), 'summary');
+    $tests['[node:body]'] = text_sanitize($instance->settings['text_processing'], $node->language()->id, $node->body[0]->getValue(), 'value');
+    $tests['[node:summary]'] = text_sanitize($instance->settings['text_processing'], $node->language()->id, $node->body[0]->getValue(), 'summary');
     $tests['[node:langcode]'] = check_plain($node->language()->id);
     $tests['[node:url]'] = url('node/' . $node->id(), $url_options);
     $tests['[node:edit-url]'] = url('node/' . $node->id() . '/edit', $url_options);
@@ -97,7 +97,7 @@ function testNodeTokenReplacement() {
 
     // Generate and test sanitized token - use full body as expected value.
     $tests = array();
-    $tests['[node:summary]'] = text_sanitize($instance['settings']['text_processing'], $node->language()->id, $node->body[0]->getValue(), 'value');
+    $tests['[node:summary]'] = text_sanitize($instance->settings['text_processing'], $node->language()->id, $node->body[0]->getValue(), 'value');
 
     // Test to make sure that we generated something for each token.
     $this->assertFalse(in_array(0, array_map('strlen', $tests)), 'No empty tokens generated for node without a summary.');
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeTypeTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeTypeTest.php
index c9e8345..6fccf94 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeTypeTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeTypeTest.php
@@ -84,7 +84,7 @@ function testNodeTypeEditing() {
     $this->drupalLogin($web_user);
 
     $instance = field_info_instance('node', 'body', 'page');
-    $this->assertEqual($instance['label'], 'Body', 'Body field was found.');
+    $this->assertEqual($instance->label(), 'Body', 'Body field was found.');
 
     // Verify that title and body fields are displayed.
     $this->drupalGet('node/add/page');
diff --git a/core/modules/node/node.tokens.inc b/core/modules/node/node.tokens.inc
index 9240497..53c0cc5 100644
--- a/core/modules/node/node.tokens.inc
+++ b/core/modules/node/node.tokens.inc
@@ -144,11 +144,11 @@ function node_tokens($type, $tokens, array $data = array(), array $options = arr
 
             // If the summary was requested and is not empty, use it.
             if ($name == 'summary' && !empty($item->summary)) {
-              $output = $sanitize ? text_sanitize($instance['settings']['text_processing'], $field_langcode, $item->getValue(), 'summary') : $item->summary;
+              $output = $sanitize ? text_sanitize($instance->settings['text_processing'], $field_langcode, $item->getValue(), 'summary') : $item->summary;
             }
             // Attempt to provide a suitable version of the 'body' field.
             else {
-              $output = $sanitize ? text_sanitize($instance['settings']['text_processing'], $field_langcode, $item->getValue(), 'value') : $item->value;
+              $output = $sanitize ? text_sanitize($instance->settings['text_processing'], $field_langcode, $item->getValue(), 'value') : $item->value;
               // A summary was requested.
               if ($name == 'summary') {
                 // Generate an optionally trimmed summary of the body field.
@@ -164,7 +164,7 @@ function node_tokens($type, $tokens, array $data = array(), array $options = arr
                   $length = $settings['trim_length'];
                 }
 
-                $output = text_summary($output, $instance['settings']['text_processing'] ? $item->format : NULL, $length);
+                $output = text_summary($output, $instance->settings['text_processing'] ? $item->format : NULL, $length);
               }
             }
             $replacements[$original] = $output;
diff --git a/core/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php b/core/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php
index 1edfd9f..7aa5115 100644
--- a/core/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php
+++ b/core/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php
@@ -94,7 +94,7 @@ function testNumberDecimalField() {
     // Display creation form.
     $this->drupalGet('entity_test/add');
     $langcode = Language::LANGCODE_NOT_SPECIFIED;
-    $this->assertFieldByName("{$this->field['field_name']}[$langcode][0][value]", '', 'Widget is displayed');
+    $this->assertFieldByName("{$this->field->id()}[$langcode][0][value]", '', 'Widget is displayed');
     $this->assertRaw('placeholder="0.00"');
 
     // Submit a signed decimal value within the allowed precision and scale.
@@ -102,7 +102,7 @@ function testNumberDecimalField() {
     $edit = array(
       'user_id' => 1,
       'name' => $this->randomName(),
-      "{$this->field['field_name']}[$langcode][0][value]" => $value,
+      "{$this->field->id()}[$langcode][0][value]" => $value,
     );
     $this->drupalPost(NULL, $edit, t('Save'));
     preg_match('|entity_test/manage/(\d+)/edit|', $this->url, $match);
@@ -122,10 +122,10 @@ function testNumberDecimalField() {
     foreach ($wrong_entries as $wrong_entry) {
       $this->drupalGet('entity_test/add');
       $edit = array(
-        "{$this->field['field_name']}[$langcode][0][value]" => $wrong_entry,
+        "{$this->field->id()}[$langcode][0][value]" => $wrong_entry,
       );
       $this->drupalPost(NULL, $edit, t('Save'));
-      $this->assertRaw(t('%name must be a number.', array('%name' => $this->field['field_name'])), 'Correctly failed to save decimal value with more than one decimal point.');
+      $this->assertRaw(t('%name must be a number.', array('%name' => $this->field->id())), 'Correctly failed to save decimal value with more than one decimal point.');
     }
 
     // Try to create entries with minus sign not in the first position.
@@ -140,10 +140,10 @@ function testNumberDecimalField() {
     foreach ($wrong_entries as $wrong_entry) {
       $this->drupalGet('entity_test/add');
       $edit = array(
-        "{$this->field['field_name']}[$langcode][0][value]" => $wrong_entry,
+        "{$this->field->id()}[$langcode][0][value]" => $wrong_entry,
       );
       $this->drupalPost(NULL, $edit, t('Save'));
-      $this->assertRaw(t('%name must be a number.', array('%name' => $this->field['field_name'])), 'Correctly failed to save decimal value with minus sign in the wrong position.');
+      $this->assertRaw(t('%name must be a number.', array('%name' => $this->field->id())), 'Correctly failed to save decimal value with minus sign in the wrong position.');
     }
   }
 
diff --git a/core/modules/options/lib/Drupal/options/Tests/OptionsFieldUITest.php b/core/modules/options/lib/Drupal/options/Tests/OptionsFieldUITest.php
index 2b45acd..66c8379 100644
--- a/core/modules/options/lib/Drupal/options/Tests/OptionsFieldUITest.php
+++ b/core/modules/options/lib/Drupal/options/Tests/OptionsFieldUITest.php
@@ -232,9 +232,9 @@ function testOptionsAllowedValuesBoolean() {
     $this->assertFieldByName('on', $on, t("The 'On' value is stored correctly."));
     $this->assertFieldByName('off', $off, t("The 'Off' value is stored correctly."));
     $field = field_info_field($this->field_name);
-    $this->assertEqual($field['settings']['allowed_values'], $allowed_values, 'The allowed value is correct');
-    $this->assertFalse(isset($field['settings']['on']), 'The on value is not saved into settings');
-    $this->assertFalse(isset($field['settings']['off']), 'The off value is not saved into settings');
+    $this->assertEqual($field->settings['allowed_values'], $allowed_values, 'The allowed value is correct');
+    $this->assertFalse(isset($field->settings['on']), 'The on value is not saved into settings');
+    $this->assertFalse(isset($field->settings['off']), 'The off value is not saved into settings');
   }
 
   /**
@@ -281,7 +281,7 @@ protected function createOptionsField($type) {
    *   element.
    * @param $result
    *   Either an expected resulting array in
-   *   $field['settings']['allowed_values'], or an expected error message.
+   *   $field->settings['allowed_values'], or an expected error message.
    * @param $message
    *   Message to display.
    */
@@ -295,7 +295,7 @@ function assertAllowedValuesInput($input_string, $result, $message) {
     else {
       field_info_cache_clear();
       $field = field_info_field($this->field_name);
-      $this->assertIdentical($field['settings']['allowed_values'], $result, $message);
+      $this->assertIdentical($field->settings['allowed_values'], $result, $message);
     }
   }
 
diff --git a/core/modules/options/lib/Drupal/options/Tests/OptionsWidgetsTest.php b/core/modules/options/lib/Drupal/options/Tests/OptionsWidgetsTest.php
index db77e61..af1e1ff 100644
--- a/core/modules/options/lib/Drupal/options/Tests/OptionsWidgetsTest.php
+++ b/core/modules/options/lib/Drupal/options/Tests/OptionsWidgetsTest.php
@@ -296,7 +296,7 @@ function testSelectListSingle() {
     // Submit form: select invalid 'none' option.
     $edit = array("card_1[$langcode]" => '_none');
     $this->drupalPost(NULL, $edit, t('Save'));
-    $this->assertRaw(t('!title field is required.', array('!title' => $instance['field_name'])), 'Cannot save a required field when selecting "none" from the select list.');
+    $this->assertRaw(t('!title field is required.', array('!title' => $instance->getFieldName())), 'Cannot save a required field when selecting "none" from the select list.');
 
     // Submit form: select first option.
     $edit = array("card_1[$langcode]" => 0);
@@ -326,8 +326,8 @@ function testSelectListSingle() {
 
     // Test optgroups.
 
-    $this->card_1['settings']['allowed_values'] = array();
-    $this->card_1['settings']['allowed_values_function'] = 'options_test_allowed_values_callback';
+    $this->card_1->settings['allowed_values'] = array();
+    $this->card_1->settings['allowed_values_function'] = 'options_test_allowed_values_callback';
     $this->card_1->save();
 
     // Display form: with no field data, nothing is selected
@@ -535,16 +535,16 @@ function testOnOffCheckbox() {
 
     // Create a test field instance.
     $fieldUpdate = $this->bool;
-    $fieldUpdate['settings']['allowed_values'] = array(0 => 0, 1 => 'MyOnValue');
+    $fieldUpdate->settings['allowed_values'] = array(0 => 0, 1 => 'MyOnValue');
     $fieldUpdate->save();
     entity_create('field_instance', array(
-      'field_name' => $this->bool['field_name'],
+      'field_name' => $this->bool->id(),
       'entity_type' => 'node',
       'bundle' => 'page',
     ))->save();
 
     entity_get_form_display('node', 'page', 'default')
-      ->setComponent($this->bool['field_name'], array(
+      ->setComponent($this->bool->id(), array(
         'type' => 'options_onoff',
       ))
       ->save();
@@ -554,7 +554,7 @@ function testOnOffCheckbox() {
     $fieldEditUrl = 'admin/structure/types/manage/page/form-display';
     $this->drupalGet($fieldEditUrl);
 
-    $field_name = $this->bool['field_name'];
+    $field_name = $this->bool->id();
     // Click on the widget settings button to open the widget settings form.
     $this->drupalPostAJAX(NULL, array(), $field_name . "_settings_edit");
 
diff --git a/core/modules/options/options.install b/core/modules/options/options.install
index 6c2c8af..ae08db2 100644
--- a/core/modules/options/options.install
+++ b/core/modules/options/options.install
@@ -9,7 +9,7 @@
  * Implements hook_field_schema().
  */
 function options_field_schema($field) {
-  switch ($field['type']) {
+  switch ($field->type) {
     case 'list_text':
       $columns = array(
         'value' => array(
diff --git a/core/modules/options/options.module b/core/modules/options/options.module
index e6ebdbe..0a47f33 100644
--- a/core/modules/options/options.module
+++ b/core/modules/options/options.module
@@ -68,9 +68,9 @@ function options_field_info() {
  * Implements hook_field_settings_form().
  */
 function options_field_settings_form($field, $instance) {
-  $settings = $field['settings'];
+  $settings = $field->settings;
 
-  switch ($field['type']) {
+  switch ($field->type) {
     case 'list_integer':
     case 'list_float':
     case 'list_text':
@@ -82,12 +82,12 @@ function options_field_settings_form($field, $instance) {
         '#element_validate' => array('options_field_settings_form_validate_allowed_values'),
         '#field_has_data' => $field->hasData(),
         '#field' => $field,
-        '#field_type' => $field['type'],
+        '#field_type' => $field->type,
         '#access' => empty($settings['allowed_values_function']),
       );
 
       $description = '<p>' . t('The possible values this field can contain. Enter one value per line, in the format key|label.');
-      if ($field['type'] == 'list_integer' || $field['type'] == 'list_float') {
+      if ($field->type == 'list_integer' || $field->type == 'list_float') {
         $description .= '<br/>' . t('The key is the stored value, and must be numeric. The label will be used in displayed values and edit forms.');
         $description .= '<br/>' . t('The label is optional: if a line contains a single number, it will be used as key and label.');
         $description .= '<br/>' . t('Lists of labels are also accepted (one label per line), only if the field does not hold any values yet. Numeric keys will be automatically generated from the positions in the list.');
@@ -142,12 +142,12 @@ function options_field_settings_form($field, $instance) {
   }
 
   // Alter the description for allowed values depending on the widget type.
-  if ($instance['widget']['type'] == 'options_onoff') {
+  /*if ($instance['widget']['type'] == 'options_onoff') {
     $form['allowed_values']['#description'] .= '<p>' . t("For a 'single on/off checkbox' widget, define the 'off' value first, then the 'on' value in the <strong>Allowed values</strong> section. Note that the checkbox will be labeled with the label of the 'on' value.") . '</p>';
   }
   elseif ($instance['widget']['type'] == 'options_buttons') {
     $form['allowed_values']['#description'] .= '<p>' . t("The 'checkboxes/radio buttons' widget will display checkboxes if the <em>Number of values</em> option is greater than 1 for this field, otherwise radios will be displayed.") . '</p>';
-  }
+  }*/
   $form['allowed_values']['#description'] .= '<p>' . t('Allowed HTML tags in labels: @tags', array('@tags' => _field_filter_xss_display_allowed_tags())) . '</p>';
 
   $form['allowed_values_function'] = array(
@@ -167,10 +167,10 @@ function options_field_settings_form($field, $instance) {
 function options_field_settings_form_validate_allowed_values($element, &$form_state) {
   $field = $element['#field'];
   $has_data = $element['#field_has_data'];
-  $field_type = $field['type'];
+  $field_type = $field->type;
   $generate_keys = ($field_type == 'list_integer' || $field_type == 'list_float') && !$has_data;
 
-  $values = options_extract_allowed_values($element['#value'], $field['type'], $generate_keys);
+  $values = options_extract_allowed_values($element['#value'], $field->type, $generate_keys);
 
   if (!is_array($values)) {
     form_error($element, t('Allowed values list: invalid input.'));
@@ -194,7 +194,7 @@ function options_field_settings_form_validate_allowed_values($element, &$form_st
 
     // Prevent removing values currently in use.
     if ($has_data) {
-      $lost_keys = array_diff(array_keys($field['settings']['allowed_values']), array_keys($values));
+      $lost_keys = array_diff(array_keys($field->settings['allowed_values']), array_keys($values));
       if (_options_values_in_use($field, $lost_keys)) {
         form_error($element, t('Allowed values list: some values are being removed while currently in use.'));
       }
@@ -368,11 +368,11 @@ function options_allowed_values_string($values) {
  * Implements hook_field_update_forbid().
  */
 function options_field_update_forbid($field, $prior_field) {
-  if ($field['module'] == 'options' && $field->hasData()) {
+  if ($field->module == 'options' && $field->hasData()) {
     // Forbid any update that removes allowed values with actual data.
-    $lost_keys = array_diff(array_keys($prior_field['settings']['allowed_values']), array_keys($field['settings']['allowed_values']));
+    $lost_keys = array_diff(array_keys($prior_field->settings['allowed_values']), array_keys($field->settings['allowed_values']));
     if (_options_values_in_use($field, $lost_keys)) {
-      throw new FieldUpdateForbiddenException(t('A list field (@field_name) with existing data cannot have its keys changed.', array('@field_name' => $field['field_name'])));
+      throw new FieldUpdateForbiddenException(t('A list field (@field_name) with existing data cannot have its keys changed.', array('@field_name' => $field->id())));
     }
   }
 }
@@ -382,11 +382,11 @@ function options_field_update_forbid($field, $prior_field) {
  */
 function _options_values_in_use($field, $values) {
   if ($values) {
-    $field = field_info_field_by_id($field['uuid']);
+    $field = field_info_field_by_id($field->uuid);
     $factory = Drupal::service('entity.query');
-    foreach ($field['bundles'] as $entity_type => $bundle) {
+    foreach ($field->getBundles() as $entity_type => $bundle) {
       $result = $factory->get($entity_type)
-        ->condition($field['field_name'] . '.value', $values)
+        ->condition($field->id() . '.value', $values)
         ->count()
         ->accessCheck(FALSE)
         ->range(0, 1)
@@ -420,9 +420,9 @@ function options_field_validate(EntityInterface $entity = NULL, $field, $instanc
   foreach ($items as $delta => $item) {
     if (!empty($item['value'])) {
       if (!empty($allowed_values) && !isset($allowed_values[$item['value']])) {
-        $errors[$field['field_name']][$langcode][$delta][] = array(
+        $errors[$field->id()][$langcode][$delta][] = array(
           'error' => 'list_illegal_value',
-          'message' => t('%name: illegal value.', array('%name' => $instance['label'])),
+          'message' => t('%name: illegal value.', array('%name' => $instance->label())),
         );
       }
     }
diff --git a/core/modules/rest/lib/Drupal/rest/LinkManager/RelationLinkManager.php b/core/modules/rest/lib/Drupal/rest/LinkManager/RelationLinkManager.php
index 0e3fd91..d71d6ce 100644
--- a/core/modules/rest/lib/Drupal/rest/LinkManager/RelationLinkManager.php
+++ b/core/modules/rest/lib/Drupal/rest/LinkManager/RelationLinkManager.php
@@ -75,13 +75,13 @@ protected function writeCache() {
     $data = array();
 
     foreach (field_info_fields() as $field_info) {
-      foreach ($field_info['bundles'] as $entity_type => $bundles) {
+      foreach ($field_info->getBundles() as $entity_type => $bundles) {
         foreach ($bundles as $bundle) {
-          $relation_uri = $this->getRelationUri($entity_type, $bundle, $field_info['field_name']);
+          $relation_uri = $this->getRelationUri($entity_type, $bundle, $field_info->id());
           $data[$relation_uri] = array(
             'entity_type' => $entity_type,
             'bundle' => $bundle,
-            'field_name' => $field_info['field_name'],
+            'field_name' => $field_info->id(),
           );
         }
       }
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationFormTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationFormTest.php
index 4404ca5..cd1a0a1 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationFormTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationFormTest.php
@@ -108,7 +108,7 @@ function testEntityFormLanguage() {
     $field->translatable = TRUE;
     $field->save();
     $field = field_info_field('body');
-    $this->assertTrue($field['translatable'], 'Field body is translatable.');
+    $this->assertTrue($field->translatable, 'Field body is translatable.');
 
     // Create a body translation and check the form language.
     $langcode2 = $this->langcodes[1];
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php
index 40a7e44..8742b05 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php
@@ -456,7 +456,7 @@ function testEntityTranslationAPI() {
     $entity = $this->reloadEntity($entity);
     $instance_id = implode('.', array($entity->entityType(), $entity->bundle(), $this->field_name));
     $instance = $this->entityManager->getStorageController('field_instance')->load($instance_id);
-    $instance['default_value_function'] = 'entity_test_field_default_value';
+    $instance->default_value_function = 'entity_test_field_default_value';
     $instance->save();
     $translation = $entity->addTranslation($langcode2);
     $this->assertEqual($translation->get($this->field_name)->value, $this->field_name . '_' . $langcode2, 'Language-aware default values correctly populated.');
diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php
index 0f660e3..45abaa6 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php
@@ -66,7 +66,7 @@ public function testEntityDisplayUpgrade() {
 
     // Check that the display key in the instance data was removed.
     $body_instance = field_info_instance('node', 'body', 'article');
-    $this->assertTrue(!isset($body_instance['display']));
+    $this->assertTrue(!isset($body_instance->display));
 
     // Check that the 'language' extra field is configured as expected.
     $expected = array(
@@ -105,7 +105,7 @@ public function testEntityFormDisplayUpgrade() {
 
     // Check that the display key in the instance data was removed.
     $body_instance = field_info_instance('node', 'body', 'article');
-    $this->assertTrue(!isset($body_instance['widget']));
+    $this->assertTrue(!isset($body_instance->widget));
 
     // Check that the 'title' extra field is configured as expected.
     $expected = array(
diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/UserPictureUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/UserPictureUpgradePathTest.php
index 2503aa5..4af9190 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/UserPictureUpgradePathTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/UserPictureUpgradePathTest.php
@@ -42,8 +42,8 @@ public function testUserPictureUpgrade() {
 
     // Retrieve the field instance and check for migrated settings.
     $instance = field_info_instance('user', 'user_picture', 'user');
-    $file = entity_load('file', $instance['settings']['default_image'][0]);
-    $this->assertIdentical($instance['settings']['default_image'][0], $file->id(), 'Default user picture has been migrated.');
+    $file = entity_load('file', $instance->settings['default_image'][0]);
+    $this->assertIdentical($instance->settings['default_image'][0], $file->id(), 'Default user picture has been migrated.');
     $this->assertEqual($file->getFileUri(), 'public://user_pictures_dir/druplicon.png', 'File id matches the uri expected.');
     $this->assertEqual($file->getFilename(), 'druplicon.png');
     $this->assertEqual($file->langcode->value, Language::LANGCODE_NOT_SPECIFIED);
@@ -53,12 +53,12 @@ public function testUserPictureUpgrade() {
     // Check file usage for the default image.
     $usage = file_usage()->listUsage($file);
     $field = field_info_field('user_picture');
-    $this->assertTrue(isset($usage['image']['default_image'][$field['uuid']]));
+    $this->assertTrue(isset($usage['image']['default_image'][$field->uuid]));
 
-    $this->assertEqual($instance['settings']['max_resolution'], '800x800', 'User picture maximum resolution has been migrated.');
-    $this->assertEqual($instance['settings']['max_filesize'], '700 KB', 'User picture maximum filesize has been migrated.');
-    $this->assertEqual($instance['description'], 'These are user picture guidelines.', 'User picture guidelines are now the user picture field description.');
-    $this->assertEqual($instance['settings']['file_directory'], 'user_pictures_dir', 'User picture directory path has been migrated.');
+    $this->assertEqual($instance->settings['max_resolution'], '800x800', 'User picture maximum resolution has been migrated.');
+    $this->assertEqual($instance->settings['max_filesize'], '700 KB', 'User picture maximum filesize has been migrated.');
+    $this->assertEqual($instance->description, 'These are user picture guidelines.', 'User picture guidelines are now the user picture field description.');
+    $this->assertEqual($instance->settings['file_directory'], 'user_pictures_dir', 'User picture directory path has been migrated.');
 
     $display_options = entity_get_display('user', 'user', 'default')->getComponent('user_picture');
     $this->assertEqual($display_options['settings']['image_style'], 'thumbnail', 'User picture image style setting has been migrated.');
diff --git a/core/modules/system/tests/modules/entity_test/entity_test.module b/core/modules/system/tests/modules/entity_test/entity_test.module
index b401470..87658f3 100644
--- a/core/modules/system/tests/modules/entity_test/entity_test.module
+++ b/core/modules/system/tests/modules/entity_test/entity_test.module
@@ -476,7 +476,7 @@ function entity_test_entity_test_mul_translation_delete(EntityInterface $transla
  *   The field language code to fill-in with the default value.
  */
 function entity_test_field_default_value(EntityInterface $entity, Field $field, FieldInstance $instance, $langcode) {
-  return array(array('value' => $field['field_name'] . '_' . $langcode));
+  return array(array('value' => $field->getFieldName() . '_' . $langcode));
 }
 
 /**
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Vocabulary.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Vocabulary.php
index 8c20176..4661b54 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Vocabulary.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Vocabulary.php
@@ -122,8 +122,8 @@ public function postSave(EntityStorageControllerInterface $storage_controller, $
       $fields = field_read_fields();
       foreach ($fields as $field_name => $field) {
         $update_field = FALSE;
-        if ($field['type'] == 'taxonomy_term_reference') {
-          foreach ($field['settings']['allowed_values'] as $key => &$value) {
+        if ($field->type == 'taxonomy_term_reference') {
+          foreach ($field->settings['allowed_values'] as $key => &$value) {
             if ($value['vocabulary'] == $this->getOriginalID()) {
               $value['vocabulary'] = $this->id();
               $update_field = TRUE;
@@ -163,14 +163,14 @@ public static function postDelete(EntityStorageControllerInterface $storage_cont
       $modified_field = FALSE;
       // Term reference fields may reference terms from more than one
       // vocabulary.
-      foreach ($taxonomy_field['settings']['allowed_values'] as $key => $allowed_value) {
+      foreach ($taxonomy_field->settings['allowed_values'] as $key => $allowed_value) {
         if (isset($vocabularies[$allowed_value['vocabulary']])) {
-          unset($taxonomy_field['settings']['allowed_values'][$key]);
+          unset($taxonomy_field->settings['allowed_values'][$key]);
           $modified_field = TRUE;
         }
       }
       if ($modified_field) {
-        if (empty($taxonomy_field['settings']['allowed_values'])) {
+        if (empty($taxonomy_field->settings['allowed_values'])) {
           $taxonomy_field->delete();
         }
         else {
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldMultipleVocabularyTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldMultipleVocabularyTest.php
index c19ce9d..9a3ce38 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldMultipleVocabularyTest.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldMultipleVocabularyTest.php
@@ -126,7 +126,7 @@ function testTaxonomyTermFieldMultipleVocabularies() {
 
     // Verify that field and instance settings are correct.
     $field_info = field_info_field($this->field_name);
-    $this->assertEqual(count($field_info['settings']['allowed_values']), 1, 'Only one vocabulary is allowed for the field.');
+    $this->assertEqual(count($field_info->settings['allowed_values']), 1, 'Only one vocabulary is allowed for the field.');
 
     // The widget should still be displayed.
     $this->drupalGet('entity_test/add');
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldTest.php
index e893001..9f994df 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldTest.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldTest.php
@@ -160,7 +160,7 @@ function testTaxonomyTermFieldChangeMachineName() {
 
     // Check that the field instance is still attached to the vocabulary.
     $field = field_info_field($this->field_name);
-    $allowed_values = $field['settings']['allowed_values'];
+    $allowed_values = $field->settings['allowed_values'];
     $this->assertEqual($allowed_values[0]['vocabulary'], $new_name, 'Index 0: Machine name was updated correctly.');
     $this->assertEqual($allowed_values[1]['vocabulary'], $new_name, 'Index 1: Machine name was updated correctly.');
     $this->assertEqual($allowed_values[2]['vocabulary'], 'foo', 'Index 2: Machine name was left untouched.');
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php
index 2195b55..9a7f023 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php
@@ -55,7 +55,7 @@ function setUp() {
       ))
       ->save();
     entity_get_display('node', 'article', 'default')
-      ->setComponent($this->instance['field_name'], array(
+      ->setComponent($this->instance->getFieldName(), array(
         'type' => 'taxonomy_term_reference_link',
       ))
       ->save();
@@ -113,7 +113,7 @@ function testTaxonomyNode() {
     $langcode = Language::LANGCODE_NOT_SPECIFIED;
     $edit["title"] = $this->randomName();
     $edit["body[$langcode][0][value]"] = $this->randomName();
-    $edit[$this->instance['field_name'] . '[' . $langcode . '][]'] = $term1->id();
+    $edit[$this->instance->getFieldName() . '[' . $langcode . '][]'] = $term1->id();
     $this->drupalPost('node/add/article', $edit, t('Save'));
 
     // Check that the term is displayed when the node is viewed.
@@ -127,8 +127,8 @@ function testTaxonomyNode() {
     $this->assertText($term1->label(), 'Term is displayed after saving the node with no changes.');
 
     // Edit the node with a different term.
-    $edit[$this->instance['field_name'] . '[' . $langcode . '][]'] = $term2->id();
-    $this->drupalPost('node/' . $node->id() . '/edit', $edit, t('Save'));
+    $edit[$this->instance->getFieldName() . '[' . $langcode . '][]'] = $term2->id();
+    $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
 
     $this->drupalGet('node/' . $node->id());
     $this->assertText($term2->label(), 'Term is displayed when viewing the node.');
@@ -146,8 +146,8 @@ function testTaxonomyNode() {
   function testNodeTermCreationAndDeletion() {
     // Enable tags in the vocabulary.
     $instance = $this->instance;
-    entity_get_form_display($instance['entity_type'], $instance['bundle'], 'default')
-      ->setComponent($instance['field_name'], array(
+    entity_get_form_display($instance->entity_type, $instance->bundle, 'default')
+      ->setComponent($instance->getFieldName(), array(
         'type' => 'taxonomy_autocomplete',
         'settings' => array(
           'placeholder' => 'Start typing here.',
@@ -167,7 +167,7 @@ function testNodeTermCreationAndDeletion() {
     $edit["body[$langcode][0][value]"] = $this->randomName();
     // Insert the terms in a comma separated list. Vocabulary 1 is a
     // free-tagging field created by the default profile.
-    $edit[$instance['field_name'] . "[$langcode]"] = drupal_implode_tags($terms);
+    $edit[$instance->getFieldName() . "[$langcode]"] = drupal_implode_tags($terms);
 
     // Verify the placeholder is there.
     $this->drupalGet('node/add/article');
@@ -511,8 +511,8 @@ function testTaxonomyGetTermByName() {
   function testReSavingTags() {
     // Enable tags in the vocabulary.
     $instance = $this->instance;
-    entity_get_form_display($instance['entity_type'], $instance['bundle'], 'default')
-      ->setComponent($instance['field_name'], array(
+    entity_get_form_display($instance->entity_type, $instance->bundle, 'default')
+      ->setComponent($instance->getFieldName(), array(
         'type' => 'taxonomy_autocomplete',
       ))
       ->save();
@@ -523,7 +523,7 @@ function testReSavingTags() {
     $edit = array();
     $edit["title"] = $this->randomName(8);
     $edit["body[$langcode][0][value]"] = $this->randomName(16);
-    $edit[$this->instance['field_name'] . '[' . $langcode . ']'] = $term->label();
+    $edit[$this->instance->getFieldName() . '[' . $langcode . ']'] = $term->label();
     $this->drupalPost('node/add/article', $edit, t('Save'));
 
     // Check that the term is displayed when editing and saving the node with no
diff --git a/core/modules/taxonomy/taxonomy.module b/core/modules/taxonomy/taxonomy.module
index 306d6d0..44de764 100644
--- a/core/modules/taxonomy/taxonomy.module
+++ b/core/modules/taxonomy/taxonomy.module
@@ -939,7 +939,7 @@ function taxonomy_field_validate(EntityInterface $entity = NULL, $field, $instan
       $validate = TRUE;
       if (!empty($item['target_id']) && $item['target_id'] != 'autocreate') {
         $validate = FALSE;
-        foreach ($field['settings']['allowed_values'] as $settings) {
+        foreach ($field->settings['allowed_values'] as $settings) {
           // If no parent is specified, check if the term is in the vocabulary.
           if (isset($settings['vocabulary']) && empty($settings['parent'])) {
             if ($settings['vocabulary'] == $terms[$item['target_id']]->bundle()) {
@@ -961,9 +961,9 @@ function taxonomy_field_validate(EntityInterface $entity = NULL, $field, $instan
         }
       }
       if (!$validate) {
-        $errors[$field['field_name']][$langcode][$delta][] = array(
+        $errors[$field->getFieldName()][$langcode][$delta][] = array(
           'error' => 'taxonomy_term_reference_illegal_value',
-          'message' => t('%name: illegal value.', array('%name' => $instance['label'])),
+          'message' => t('%name: illegal value.', array('%name' => $instance->label())),
         );
       }
     }
@@ -1123,9 +1123,9 @@ function taxonomy_build_node_index($node) {
     // Collect a unique list of all the term IDs from all node fields.
     $tid_all = array();
     foreach (field_info_instances('node', $node->getType()) as $instance) {
-      $field_name = $instance['field_name'];
+      $field_name = $instance->getFieldName();
       $field = field_info_field($field_name);
-      if ($field['module'] == 'taxonomy' && $field['storage']['type'] == 'field_sql_storage') {
+      if ($field->module == 'taxonomy' && $field->storage['type'] == 'field_sql_storage') {
         foreach ($node->getTranslationLanguages() as $language) {
           foreach ($node->getTranslation($language->id)->$field_name as $item) {
             if (!$item->isEmpty()) {
diff --git a/core/modules/taxonomy/taxonomy.views.inc b/core/modules/taxonomy/taxonomy.views.inc
index 5646268..36178f6 100644
--- a/core/modules/taxonomy/taxonomy.views.inc
+++ b/core/modules/taxonomy/taxonomy.views.inc
@@ -341,16 +341,16 @@ function taxonomy_field_views_data($field) {
     foreach ($table_data as $field_name => $field_data) {
       if (isset($field_data['filter']) && $field_name != 'delta') {
         $data[$table_name][$field_name]['filter']['id'] = 'taxonomy_index_tid';
-        $data[$table_name][$field_name]['filter']['vocabulary'] = $field['settings']['allowed_values'][0]['vocabulary'];
+        $data[$table_name][$field_name]['filter']['vocabulary'] = $field->settings['allowed_values'][0]['vocabulary'];
       }
     }
 
     // Add the relationship only on the tid field.
-    $data[$table_name][$field['field_name'] . '_target_id']['relationship'] = array(
+    $data[$table_name][$field->id() . '_target_id']['relationship'] = array(
       'id' => 'standard',
       'base' => 'taxonomy_term_data',
       'base field' => 'tid',
-      'label' => t('term from !field_name', array('!field_name' => $field['field_name'])),
+      'label' => t('term from !field_name', array('!field_name' => $field->id())),
     );
 
   }
@@ -364,11 +364,11 @@ function taxonomy_field_views_data($field) {
  * Views integration to provide reverse relationships on term references.
  */
 function taxonomy_field_views_data_views_data_alter(&$data, $field) {
-  foreach ($field['bundles'] as $entity_type => $bundles) {
+  foreach ($field->getBundles() as $entity_type => $bundles) {
     $entity_info = entity_get_info($entity_type);
-    $pseudo_field_name = 'reverse_' . $field['field_name'] . '_' . $entity_type;
+    $pseudo_field_name = 'reverse_' . $field->id() . '_' . $entity_type;
 
-    list($label, $all_labels) = field_views_field_label($field['field_name']);
+    list($label, $all_labels) = field_views_field_label($field->id());
     $entity = $entity_info['label'];
     if ($entity == t('Node')) {
       $entity = t('Content');
@@ -378,12 +378,12 @@ function taxonomy_field_views_data_views_data_alter(&$data, $field) {
       'title' => t('@entity using @field', array('@entity' => $entity, '@field' => $label)),
       'help' => t('Relate each @entity with a @field set to the term.', array('@entity' => $entity, '@field' => $label)),
       'id' => 'entity_reverse',
-      'field_name' => $field['field_name'],
+      'field_name' => $field->id(),
       'field table' => _field_sql_storage_tablename($field),
-      'field field' => $field['field_name'] . '_target_id',
+      'field field' => $field->id() . '_target_id',
       'base' => $entity_info['base_table'],
       'base field' => $entity_info['entity_keys']['id'],
-      'label' => t('!field_name', array('!field_name' => $field['field_name'])),
+      'label' => t('!field_name', array('!field_name' => $field->id())),
       'join_extra' => array(
         0 => array(
           'field' => 'entity_type',
diff --git a/core/modules/text/lib/Drupal/text/TextProcessed.php b/core/modules/text/lib/Drupal/text/TextProcessed.php
index 352420d..fe7b181 100644
--- a/core/modules/text/lib/Drupal/text/TextProcessed.php
+++ b/core/modules/text/lib/Drupal/text/TextProcessed.php
@@ -69,7 +69,7 @@ public function getValue($langcode = NULL) {
     $entity = $field->getParent();
     $instance = field_info_instance($entity->entityType(), $field->getName(), $entity->bundle());
 
-    if (!empty($instance['settings']['text_processing']) && $this->format->getValue()) {
+    if (!empty($instance->settings['text_processing']) && $this->format->getValue()) {
       return check_markup($this->text->getValue(), $this->format->getValue(), $entity->language()->id);
     }
     else {
diff --git a/core/modules/text/text.install b/core/modules/text/text.install
index 72d879f..d87d7f7 100644
--- a/core/modules/text/text.install
+++ b/core/modules/text/text.install
@@ -9,12 +9,12 @@
  * Implements hook_field_schema().
  */
 function text_field_schema($field) {
-  switch ($field['type']) {
+  switch ($field->type) {
     case 'text':
       $columns = array(
         'value' => array(
           'type' => 'varchar',
-          'length' => $field['settings']['max_length'],
+          'length' => $field->settings['max_length'],
           'not null' => FALSE,
         ),
       );
diff --git a/core/modules/views_ui/admin.inc b/core/modules/views_ui/admin.inc
index d05888f..8cdf6e3 100644
--- a/core/modules/views_ui/admin.inc
+++ b/core/modules/views_ui/admin.inc
@@ -226,8 +226,8 @@ function views_ui_taxonomy_autocomplete_validate($element, &$form_state) {
     // vocabulary IDs.
     $field = field_info_field($element['#field_name']);
     $vocabularies = array();
-    if (!empty($field['settings']['allowed_values'])) {
-      foreach ($field['settings']['allowed_values'] as $tree) {
+    if (!empty($field->settings['allowed_values'])) {
+      foreach ($field->settings['allowed_values'] as $tree) {
         if ($vocabulary = entity_load('taxonomy_vocabulary', $tree['vocabulary'])) {
           $vocabularies[$vocabulary->id()] = $tree['vocabulary'];
         }
diff --git a/core/scripts/generate-d7-content.sh b/core/scripts/generate-d7-content.sh
index 87ec22a..8a86cef 100644
--- a/core/scripts/generate-d7-content.sh
+++ b/core/scripts/generate-d7-content.sh
@@ -98,7 +98,7 @@
   foreach ($node_types as $bundle) {
     $instance = array(
       'label' => $vocabulary->name,
-      'field_name' => $field['field_name'],
+      'field_name' => $field->id(),
       'bundle' => $bundle,
       'entity_type' => 'node',
       'settings' => array(),
