diff --git a/core/lib/Drupal/Core/Entity/EntityFormController.php b/core/lib/Drupal/Core/Entity/EntityFormController.php
index ceb09de..0bdcb31 100644
--- a/core/lib/Drupal/Core/Entity/EntityFormController.php
+++ b/core/lib/Drupal/Core/Entity/EntityFormController.php
@@ -459,15 +459,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 2f7156a..a7609c7 100644
--- a/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php
+++ b/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php
@@ -120,7 +120,8 @@ 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())) {
+          $schema = $field->getSchema('columns');
+          if (isset($schema[$next]) || in_array($next, Field::getReservedColumns())) {
             // Use it.
             $column = $next;
             // Do not process it again.
@@ -138,7 +139,7 @@ function addField($field, $type, $langcode) {
 
             // Get the field definitions form a mocked entity.
             $entity = entity_create($entity_type, array());
-            $propertyDefinitions = $entity->{$field['field_name']}->getPropertyDefinitions();
+            $propertyDefinitions = $entity->{$field->id()}->getPropertyDefinitions();
 
             // If the column is not yet known, ie. the
             // $node->field_image->entity case then use first property as
@@ -157,7 +158,7 @@ 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->id(), $column);
       }
       // This is an entity property (non-configurable field).
       else {
@@ -240,10 +241,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->id();
     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->cardinality != 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 da5ac4f..00f575c 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'));
     // Place the block.
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 37dbf79..9048298 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 296a3e2..3787de8 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.module b/core/modules/content_translation/content_translation.module
index 56d9508..200aa50 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()) {
@@ -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 08cc693..519dcfa 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/lib/Drupal/datetime/Tests/DatetimeFieldTest.php b/core/modules/datetime/lib/Drupal/datetime/Tests/DatetimeFieldTest.php
index af66e0d..7b1a5d3 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 e14e0d2..ec08030 100644
--- a/core/modules/edit/lib/Drupal/edit/Form/EditFieldForm.php
+++ b/core/modules/edit/lib/Drupal/edit/Form/EditFieldForm.php
@@ -118,7 +118,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.install b/core/modules/entity_reference/entity_reference.install
index c40d3ea..eee8613 100644
--- a/core/modules/entity_reference/entity_reference.install
+++ b/core/modules/entity_reference/entity_reference.install
@@ -32,8 +32,8 @@ function entity_reference_field_schema($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/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/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 312ebb5..305e253 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 5bab381..fb3f854 100644
--- a/core/modules/field/field.attach.inc
+++ b/core/modules/field/field.attach.inc
@@ -170,8 +170,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);
@@ -260,8 +260,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.
@@ -277,7 +277,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);
@@ -296,7 +296,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) {
@@ -366,7 +366,7 @@ function _field_invoke_get_instances($entity_type, $bundle, $options) {
       // Single-field mode by field id: we need to loop on each instance to
       // find the right one.
       foreach ($instances as $instance) {
-        if ($instance['field_id'] == $options['field_id']) {
+        if ($instance->getField()->uuid == $options['field_id']) {
           $instances = array($instance);
           break;
         }
@@ -390,7 +390,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());
   };
 }
 
@@ -464,7 +464,7 @@ function _field_invoke_widget_target($form_display) {
  *
  *       // Only for multiple widgets:
  *       '#entity_type' => The name of the entity type,
- *       '#bundle' => $instance['bundle'],
+ *       '#bundle' => $instance->bundle,
  *       // The remaining elements in the sub-array depend on the widget.
  *       '#type' => The type of the widget,
  *       ...
@@ -699,7 +699,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);
@@ -863,13 +863,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->getFieldName();
     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;
       }
     }
   }
@@ -904,11 +904,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;
     }
   }
 
@@ -940,9 +940,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.
@@ -973,9 +973,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->getFieldName());
+    $field_id = $field->uuid;
+    $storages[$field->storage['type']][$field_id] = $field_id;
   }
 
   // Field storage backends delete their data.
@@ -1039,8 +1039,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;
@@ -1085,7 +1085,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);
@@ -1130,7 +1130,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;
@@ -1160,7 +1160,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();
diff --git a/core/modules/field/field.crud.inc b/core/modules/field/field.crud.inc
index c66fd54..93443c4 100644
--- a/core/modules/field/field.crud.inc
+++ b/core/modules/field/field.crud.inc
@@ -241,7 +241,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.
@@ -251,13 +251,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'])) {
@@ -291,7 +291,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);
     }
@@ -320,7 +320,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) {
@@ -340,12 +340,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.
@@ -365,18 +365,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.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.info.inc b/core/modules/field/field.info.inc
index 824d74e..845f73d 100644
--- a/core/modules/field/field.info.inc
+++ b/core/modules/field/field.info.inc
@@ -129,7 +129,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;
@@ -287,8 +287,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 3203f2e..2e0db6d 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;
         }
@@ -491,12 +491,12 @@ function field_sync_field_status() {
  */
 function field_get_default_value(EntityInterface $entity, $field, $instance, $langcode = NULL) {
   $items = array();
-  if (!empty($instance['default_value_function'])) {
-    $function = $instance['default_value_function'];
+  if (!empty($instance->default_value_function)) {
+    $function = $instance->default_value_function;
     $items = $function($entity, $field, $instance, $langcode);
   }
-  elseif (!empty($instance['default_value'])) {
-    $items = $instance['default_value'];
+  elseif (!empty($instance->default_value)) {
+    $items = $instance->default_value;
   }
   return $items;
 }
@@ -791,7 +791,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 ca33a31..961c465 100644
--- a/core/modules/field/field.multilingual.inc
+++ b/core/modules/field/field.multilingual.inc
@@ -1,6 +1,7 @@
 <?php
 
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\field\FieldInterface;
 
 /**
  * @file
@@ -81,13 +82,13 @@
  * @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
@@ -172,8 +173,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);
 }
 
 /**
@@ -266,17 +267,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.views.inc b/core/modules/field/field.views.inc
index e5dea3b..15d6773 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,
@@ -316,10 +318,10 @@ function field_views_field_default_views_data($field) {
         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']));
+              $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/FieldInfo.php b/core/modules/field/lib/Drupal/field/FieldInfo.php
index 2639c25..112661f 100644
--- a/core/modules/field/lib/Drupal/field/FieldInfo.php
+++ b/core/modules/field/lib/Drupal/field/FieldInfo.php
@@ -234,7 +234,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 +243,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->id()] = $field->uuid;
       }
     }
 
@@ -280,9 +280,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 +328,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 +367,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;
@@ -408,10 +408,10 @@ public function getBundleInstances($entity_type, $bundle) {
 
       // Extract the field definitions and save them in the "static" cache.
       foreach ($info['fields'] as $field) {
-        if (!isset($this->fieldsById[$field['uuid']])) {
-          $this->fieldsById[$field['uuid']] = $field;
+        if (!isset($this->fieldsById[$field->uuid])) {
+          $this->fieldsById[$field->uuid] = $field;
           if (!$field['deleted']) {
-            $this->fieldIdsByName[$field['field_name']] = $field['uuid'];
+            $this->fieldIdsByName[$field->getFieldName()] = $field->uuid;
           }
         }
       }
@@ -451,17 +451,17 @@ 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->type);
+          $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;
           }
         }
       }
@@ -484,7 +484,7 @@ public function getBundleInstances($entity_type, $bundle) {
       'fields' => array()
     );
     foreach ($instances as $instance) {
-      $cache['fields'][] = $this->fieldsById[$instance['field_id']];
+      $cache['fields'][] = $this->fieldsById[$instance->getField()->uuid];
     }
     $this->cacheBackend->set("field_info:bundle:$entity_type:$bundle", $cache, CacheBackendInterface::CACHE_PERMANENT, array('field_info' => TRUE));
 
@@ -564,8 +564,8 @@ public function getBundleExtraFields($entity_type, $bundle) {
    */
   public function prepareField($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,11 +583,11 @@ public function prepareField($field) {
    */
   public function prepareInstance($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 d2a0b85..adc9930 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, \Serializable {
+interface FieldInstanceInterface extends ConfigEntityInterface, FieldDefinitionInterface, \Serializable {
 
   /**
    * 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 132bc39..f84bdf2 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, \Serializable {
+interface FieldInterface extends ConfigEntityInterface, FieldDefinitionInterface, \Serializable {
 
   /**
    * 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/Core/Entity/Field.php b/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/Field.php
index bccc64b..bab95db 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/Field.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/Field.php
@@ -487,7 +487,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);
@@ -508,6 +508,10 @@ public function getSchema() {
       $this->schema = $schema;
     }
 
+    if (!empty($key)) {
+      return $this->schema[$key];
+    }
+
     return $this->schema;
   }
 
@@ -547,10 +551,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'];
       }
     }
@@ -651,62 +660,6 @@ public function isFieldRequired() {
   /**
    * {@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});
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
   public function serialize() {
     // Only store the definition, not external objects or derived data.
     return serialize($this->getExportProperties());
diff --git a/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/FieldInstance.php b/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/FieldInstance.php
index 9628256..cba93c1 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/FieldInstance.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/FieldInstance.php
@@ -562,6 +562,7 @@ public function isFieldRequired() {
     return $this->required;
   }
 
+
   /**
    * {@inheritdoc}
    */
@@ -572,46 +573,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});
-  }
-
-  /**
-   * {@inheritdoc}
-   */
   public function serialize() {
     // Only store the definition, not external objects or derived data.
     return serialize($this->getExportProperties());
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 7c7a343..0f98887 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/Tests/BulkDeleteTest.php b/core/modules/field/lib/Drupal/field/Tests/BulkDeleteTest.php
index 9637826..7dc5c54 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/FieldAccessTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldAccessTest.php
index 16fabe5..4e45929 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/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 cade864..e5a9eb6 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FieldInstanceCrudTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FieldInstanceCrudTest.php
@@ -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']);
@@ -211,8 +211,8 @@ function testDeleteFieldInstance() {
     // 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/FormTest.php b/core/modules/field/lib/Drupal/field/Tests/FormTest.php
index b7c600e..05be28f 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FormTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FormTest.php
@@ -80,10 +80,10 @@ function setUp() {
   function testFieldFormSingle() {
     $field = $this->field_single;
     $field_name = $field['field_name'];
-    $this->instance['field_name'] = $field_name;
+    $this->instance->field_name = $field_name;
     entity_create('field_entity', $field)->save();
     entity_create('field_instance', $this->instance)->save();
-    entity_get_form_display($this->instance['entity_type'], $this->instance['bundle'], 'default')
+    entity_get_form_display($this->instance->entity_type, $this->instance->bundle, 'default')
       ->setComponent($field_name)
       ->save();
     $langcode = Language::LANGCODE_NOT_SPECIFIED;
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 8658c52..867b1cf 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->id()][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]->id()][$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]->id()] = 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->id()]['id'] = $field->id();
+      $view->display_handler->options['fields'][$field->id()]['table'] = 'field_data_' . $field->id();
+      $view->display_handler->options['fields'][$field->id()]['field'] = $field->id();
     }
   }
 
@@ -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']}[Language::LANGCODE_NOT_SPECIFIED][0]['value'];
+        $rendered_field = $view->style_plugin->getField($i, $field->id());
+        $expected_field = $this->nodes[$i]->{$field->id()}[Language::LANGCODE_NOT_SPECIFIED][0]['value'];
         $this->assertEqual($rendered_field, $expected_field);
       }
     }
@@ -119,8 +119,8 @@ public function _testSimpleFieldRender() {
   public function _testFormatterSimpleFieldRender() {
     $view = views_get_view('test_view_fieldapi');
     $this->prepareView($view);
-    $view->displayHandlers->get('default')->options['fields'][$this->fields[0]['field_name']]['type'] = 'text_trimmed';
-    $view->displayHandlers->get('default')->options['fields'][$this->fields[0]['field_name']]['settings'] = array(
+    $view->displayHandlers->get('default')->options['fields'][$this->fields[0]->id()]['type'] = 'text_trimmed';
+    $view->displayHandlers->get('default')->options['fields'][$this->fields[0]->id()]['settings'] = array(
       'trim_length' => 3,
     );
     $this->executeView($view);
@@ -128,14 +128,14 @@ public function _testFormatterSimpleFieldRender() {
     // Take sure that the formatter works as expected.
     // @TODO: actually there should be a specific formatter.
     for ($i = 0; $i < 2; $i++) {
-      $rendered_field = $view->style_plugin->getField($i, $this->fields[0]['field_name']);
+      $rendered_field = $view->style_plugin->getField($i, $this->fields[0]->id());
       $this->assertEqual(strlen($rendered_field), 3);
     }
   }
 
   public function _testMultipleFieldRender() {
     $view = views_get_view('test_view_fieldapi');
-    $field_name = $this->fields[3]['field_name'];
+    $field_name = $this->fields[3]->id();
 
     // Test delta limit.
     $this->prepareView($view);
@@ -155,7 +155,7 @@ public function _testMultipleFieldRender() {
     }
 
     // Test that an empty field is rendered without error.
-    $rendered_field = $view->style_plugin->getField(4, $this->fields[4]['field_name']);
+    $rendered_field = $view->style_plugin->getField(4, $this->fields[4]->id());
 
     $view->destroy();
 
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 db22e81..c4c0fe4 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' && !user_access('view test_view_field content')) {
+  if ($field->id() == 'test_view_field' && $op == 'view' && !user_access('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..0440be1 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
@@ -194,8 +194,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);
     }
   }
diff --git a/core/modules/field_sql_storage/field_sql_storage.module b/core/modules/field_sql_storage/field_sql_storage.module
index 5e3e0dd..5b61765 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\Plugin\Core\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->id()}";
   }
 }
 
@@ -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);
@@ -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_ui/field_ui.admin.inc b/core/modules/field_ui/field_ui.admin.inc
new file mode 100644
index 0000000..e8c7776
--- /dev/null
+++ b/core/modules/field_ui/field_ui.admin.inc
@@ -0,0 +1,139 @@
+<?php
+
+/**
+ * @file
+ * Administrative interface for custom field type creation.
+ */
+
+/**
+ * Page callback: Lists all defined fields for quick reference.
+ *
+ * @see field_ui_menu()
+ */
+function field_ui_fields_list() {
+  $instances = field_info_instances();
+  $field_types = field_info_field_types();
+  $bundles = entity_get_bundles();
+  $entity_manager = Drupal::entityManager();
+
+  $modules = system_rebuild_module_data();
+
+  $header = array(
+    t('Field name'),
+    array('data' => t('Field type'), 'class' => array(RESPONSIVE_PRIORITY_MEDIUM)),
+    t('Used in'),
+  );
+  $rows = array();
+  foreach ($instances as $entity_type => $type_bundles) {
+    foreach ($type_bundles as $bundle => $bundle_instances) {
+      foreach ($bundle_instances as $field_name => $instance) {
+        $field = field_info_field($field_name);
+
+        // Initialize the row if we encounter the field for the first time.
+        if (!isset($rows[$field_name])) {
+          $rows[$field_name]['class'] = $field->locked ? array('menu-disabled') : array('');
+          $rows[$field_name]['data'][0] = $field->locked ? t('@field_name (Locked)', array('@field_name' => $field_name)) : $field_name;
+          $module_name = $field_types[$field->type]['module'];
+          $rows[$field_name]['data'][1] = $field_types[$field->type]['label'] . ' ' . t('(module: !module)', array('!module' => $modules[$module_name]->info['name']));
+        }
+
+        // Add the current instance.
+        $admin_path = $entity_manager->getAdminPath($entity_type, $bundle);
+        $rows[$field_name]['data'][2][] = $admin_path ? l($bundles[$entity_type][$bundle]['label'], $admin_path . '/fields') : $bundles[$entity_type][$bundle]['label'];
+      }
+    }
+  }
+  foreach ($rows as $field_name => $cell) {
+    $rows[$field_name]['data'][2] = implode(', ', $cell['data'][2]);
+  }
+  if (empty($rows)) {
+    $output = t('No fields have been defined yet.');
+  }
+  else {
+    // Sort rows by field name.
+    ksort($rows);
+    $output = theme('table', array('header' => $header, 'rows' => $rows));
+  }
+  return $output;
+}
+
+/**
+ * Returns HTML for Field UI overview tables.
+ *
+ * @param $variables
+ *   An associative array containing:
+ *   - elements: An associative array containing a Form API structure to be
+ *     rendered as a table.
+ *
+ * @ingroup themeable
+ */
+function theme_field_ui_table($variables) {
+  $elements = $variables['elements'];
+  $table = array();
+
+  // Add table headers and attributes.
+  foreach (array('header', 'attributes') as $key) {
+    if (isset($elements["#$key"])) {
+      $table[$key] = $elements["#$key"];
+    }
+  }
+
+  // Determine the colspan to use for region rows, by checking the number of
+  // columns in the headers.
+  $columns_count = 0;
+  foreach ($table['header'] as $header) {
+    $columns_count += (is_array($header) && isset($header['colspan']) ? $header['colspan'] : 1);
+  }
+
+  // Render rows, region by region.
+  foreach ($elements['#regions'] as $region_name => $region) {
+    $region_name_class = drupal_html_class($region_name);
+
+    // Add region rows.
+    if (isset($region['title']) && empty($region['invisible'])) {
+      $table['rows'][] = array(
+        'class' => array('region-title', 'region-' . $region_name_class . '-title'),
+        'no_striping' => TRUE,
+        'data' => array(
+          array('data' => $region['title'], 'colspan' => $columns_count),
+        ),
+      );
+    }
+    if (isset($region['message'])) {
+      $class = (empty($region['rows_order']) ? 'region-empty' : 'region-populated');
+      $table['rows'][] = array(
+        'class' => array('region-message', 'region-' . $region_name_class . '-message', $class),
+        'no_striping' => TRUE,
+        'data' => array(
+          array('data' => $region['message'], 'colspan' => $columns_count),
+        ),
+      );
+    }
+
+    // Add form rows, in the order determined at pre-render time.
+    foreach ($region['rows_order'] as $name) {
+      $element = $elements[$name];
+
+      $row = array('data' => array());
+      if (isset($element['#attributes'])) {
+        $row += $element['#attributes'];
+      }
+
+      // Render children as table cells.
+      foreach (element_children($element) as $cell_key) {
+        $child = &$element[$cell_key];
+        // Do not render a cell for children of #type 'value'.
+        if (!(isset($child['#type']) && $child['#type'] == 'value')) {
+          $cell = array('data' => drupal_render($child));
+          if (isset($child['#cell_attributes'])) {
+            $cell += $child['#cell_attributes'];
+          }
+          $row['data'][] = $cell;
+        }
+      }
+      $table['rows'][] = $row;
+    }
+  }
+
+  return theme('table', $table);
+}
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 621c08d..ffbffa3 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' => 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' => t('Locked'));
         $table[$name]['#attributes']['class'][] = 'menu-disabled';
       }
@@ -430,7 +430,7 @@ public function submitForm(array &$form, array &$form_state) {
     if (!empty($form_values['_add_existing_field']['field_name'])) {
       $values = $form_values['_add_existing_field'];
       $field = field_info_field($values['field_name']);
-      if (!empty($field['locked'])) {
+      if (!empty($field->locked)) {
         drupal_set_message(t('The field %label cannot be added because it is locked.', array('%label' => $values['label'])), 'error');
       }
       else {
@@ -498,17 +498,17 @@ 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'])
+            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'])) {
+              && (empty($field->entity_types) || in_array($this->entity_type, $field->entity_types))
+              && empty($field_types[$field->getFieldType()]['no_ui'])) {
               $info[$instance['field_name']] = array(
                 'type' => $field['type'],
                 'type_label' => $field_types[$field['type']]['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 e53eec9..e4533fd 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
@@ -77,7 +77,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(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 305596f..5c08226 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
@@ -87,7 +87,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.
@@ -123,10 +123,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
@@ -136,9 +136,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);
+    $form['field']['settings'] += $this->getFieldItem($entity, $field->getFieldName())->settingsForm($form, $form_state);
 
     $form['actions'] = array('#type' => 'actions');
     $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save field settings'));
@@ -176,7 +176,7 @@ public function submitForm(array &$form, array &$form_state) {
     // Merge incoming form values into the existing field.
     $field = Field::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 046e012..4770bef 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
@@ -92,8 +92,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();
     $entity_form_display = entity_get_form_display($entity_type, $bundle, 'default');
     $bundles = entity_get_bundles();
@@ -106,11 +106,11 @@ public function buildForm(array $form, array &$form_state, FieldInstanceInterfac
     $form['#field'] = $field;
     $form['#entity_form_display'] = $entity_form_display;
     // 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);
     $form['#entity']->field_ui_default_value = TRUE;
 
-    if (!empty($field['locked'])) {
+    if (!empty($field->locked)) {
       $form['locked'] = array(
         '#markup' => t('The field %field is locked and cannot be edited.', array('%field' => $this->instance->label())),
       );
@@ -125,7 +125,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',
@@ -140,7 +140,7 @@ public function buildForm(array $form, array &$form_state, FieldInstanceInterfac
     $form['instance']['label'] = array(
       '#type' => 'textfield',
       '#title' => t('Label'),
-      '#default_value' => $this->instance->label() ?: $field['field_name'],
+      '#default_value' => $this->instance->label() ?: $field->getFieldName(),
       '#required' => TRUE,
       '#weight' => -20,
     );
@@ -148,7 +148,7 @@ public function buildForm(array $form, array &$form_state, FieldInstanceInterfac
     $form['instance']['description'] = array(
       '#type' => 'textarea',
       '#title' => t('Help text'),
-      '#default_value' => !empty($this->instance['description']) ? $this->instance['description'] : '',
+      '#default_value' => !empty($this->instance->description) ? $this->instance->description : '',
       '#rows' => 5,
       '#description' => 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 />' . t('This field supports tokens.'),
       '#weight' => -10,
@@ -157,7 +157,7 @@ public function buildForm(array $form, array &$form_state, FieldInstanceInterfac
     $form['instance']['required'] = array(
       '#type' => 'checkbox',
       '#title' => t('Required field'),
-      '#default_value' => !empty($this->instance['required']),
+      '#default_value' => !empty($this->instance->required),
       '#weight' => -5,
     );
 
@@ -166,7 +166,7 @@ public function buildForm(array $form, array &$form_state, FieldInstanceInterfac
     $form['instance']['settings']['#weight'] = 10;
 
     // Add handling for default value if not provided by any other module.
-    if (field_behaviors_widget('default_value', $this->instance) == FIELD_BEHAVIOR_DEFAULT && empty($this->instance['default_value_function'])) {
+    if (field_behaviors_widget('default_value', $this->instance) == FIELD_BEHAVIOR_DEFAULT && empty($this->instance->default_value_function)) {
       $form['instance']['default_value_widget'] = $this->getDefaultValueWidget($field, $form, $form_state);
     }
 
@@ -189,7 +189,7 @@ public function buildForm(array $form, array &$form_state, FieldInstanceInterfac
   public function validateForm(array &$form, array &$form_state) {
     // Take the incoming values as the $this->instance definition, so that the 'default
     // value' gets validated using the instance settings being submitted.
-    $field_name = $this->instance['field_name'];
+    $field_name = $this->instance->getFieldName();
     $entity = $form['#entity'];
     $entity_form_display = $form['#entity_form_display'];
 
@@ -218,7 +218,7 @@ public function validateForm(array &$form, array &$form_state) {
    * {@inheritdoc}
    */
   public function submitForm(array &$form, array &$form_state) {
-    $field_name = $this->instance['field_name'];
+    $field_name = $this->instance->getFieldName();
     $entity = $form['#entity'];
     $entity_form_display = $form['#entity_form_display'];
 
@@ -253,7 +253,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));
   }
 
   /**
@@ -283,8 +283,8 @@ protected function getDefaultValueWidget($field, array &$form, &$form_state) {
     // instead of the hidden widget.
     // @todo Clean this up since we don't have $this->instance['widget'] anymore.
     //   see https://drupal.org/node/2028759
-    if ($this->instance['widget']['type'] == 'hidden') {
-      $field_type = $this->fieldTypeManager->getDefinition($field['type']);
+    /*if ($this->instance['widget']['type'] == 'hidden') {
+      $field_type = $this->fieldTypeManager->getDefinition($field->getFieldType());
       $default_widget = $this->widgetManager->getDefinition($field_type['default_widget']);
 
       $this->instance['widget'] = array(
@@ -292,13 +292,13 @@ protected function getDefaultValueWidget($field, array &$form, &$form_state) {
         'settings' => $default_widget['settings'],
         'weight' => 0,
       );
-    }
+    }*/
 
     // Insert the widget. Since we do not use the "official" instance definition,
     // the whole flow cannot use field_invoke_method().
     $items = $entity->getNGEntity()->{$this->instance->getField()->id};
-    if (!empty($this->instance['default_value'])) {
-      $items->setValue((array) $this->instance['default_value']);
+    if (!empty($this->instance->default_value)) {
+      $items->setValue((array) $this->instance->default_value);
     }
     $element += $entity_form_display->getRenderer($this->instance->getField()->id)->form($entity, Language::LANGCODE_NOT_SPECIFIED, $items, $element, $form_state);
 
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/file/file.field.inc b/core/modules/file/file.field.inc
index 6445527..2b0afc7 100644
--- a/core/modules/file/file.field.inc
+++ b/core/modules/file/file.field.inc
@@ -217,8 +217,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.
diff --git a/core/modules/file/file.module b/core/modules/file/file.module
index d37a1ba..f08ab24 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 3582893..d8fb273 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/tests/file_module_test.module b/core/modules/file/tests/file_module_test.module
index 19096f9..d0c4757 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 4621ddd..7fee618 100644
--- a/core/modules/forum/forum.module
+++ b/core/modules/forum/forum.module
@@ -172,7 +172,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) {
         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.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/Plugin/Core/Entity/ImageStyle.php b/core/modules/image/lib/Drupal/image/Plugin/Core/Entity/ImageStyle.php
index 73976f9..0ed510a 100644
--- a/core/modules/image/lib/Drupal/image/Plugin/Core/Entity/ImageStyle.php
+++ b/core/modules/image/lib/Drupal/image/Plugin/Core/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 2c1ae39..705e47a 100644
--- a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDefaultImagesTest.php
+++ b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDefaultImagesTest.php
@@ -67,7 +67,7 @@ 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();
@@ -142,7 +142,7 @@ 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.
@@ -177,7 +177,7 @@ 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
@@ -216,7 +216,7 @@ 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 8ec6727..de1b1cc 100644
--- a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php
+++ b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php
@@ -232,7 +232,7 @@ function testImageFieldDefaultImage() {
     // Clear field info cache so the new default image is detected.
     field_info_cache_clear();
     $field = field_info_field($field_name);
-    $image = file_load($field['settings']['default_image']);
+    $image = file_load($field->settings['default_image']);
     $this->assertTrue($image->isPermanent(), 'The default image status is permanent.');
     $default_output = theme('image', array('uri' => $image->getFileUri()));
     $this->drupalGet('node/' . $node->id());
@@ -260,7 +260,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());
@@ -274,7 +274,7 @@ function testImageFieldDefaultImage() {
     field_info_cache_clear();
 
     $private_field = field_info_field($private_field_name);
-    $image = file_load($private_field['settings']['default_image']);
+    $image = file_load($private_field->settings['default_image']);
     $this->assertEqual('private', file_uri_scheme($image->getFileUri()), 'Default image uses private:// scheme.');
     $this->assertTrue($image->isPermanent(), 'The default image status is permanent.');
     // Create a new node with no image attached and ensure that default private
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 b4033ff..0a5f9af 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 acba6b6..36af4dc 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
@@ -280,11 +280,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 6416a77..088b864 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->title);
-    $tests['[node:body]'] = text_sanitize($instance['settings']['text_processing'], $node->langcode, $node->body[$node->langcode][0], 'value');
-    $tests['[node:summary]'] = text_sanitize($instance['settings']['text_processing'], $node->langcode, $node->body[$node->langcode][0], 'summary');
+    $tests['[node:body]'] = text_sanitize($instance->settings['text_processing'], $node->langcode, $node->body[$node->langcode][0], 'value');
+    $tests['[node:summary]'] = text_sanitize($instance->settings['text_processing'], $node->langcode, $node->body[$node->langcode][0], 'summary');
     $tests['[node:langcode]'] = check_plain($node->langcode);
     $tests['[node:url]'] = url('node/' . $node->id(), $url_options);
     $tests['[node:edit-url]'] = url('node/' . $node->id() . '/edit', $url_options);
@@ -96,7 +96,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->langcode, $node->body[$node->langcode][0], 'value');
+    $tests['[node:summary]'] = text_sanitize($instance->settings['text_processing'], $node->langcode, $node->body[$node->langcode][0], '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/number/lib/Drupal/number/Tests/NumberFieldTest.php b/core/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php
index ad947e4..7314362 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/OptionsFieldTest.php b/core/modules/options/lib/Drupal/options/Tests/OptionsFieldTest.php
index 218e413..7125de6 100644
--- a/core/modules/options/lib/Drupal/options/Tests/OptionsFieldTest.php
+++ b/core/modules/options/lib/Drupal/options/Tests/OptionsFieldTest.php
@@ -70,7 +70,7 @@ function testUpdateAllowedValues() {
     $this->assertTrue(empty($form[$this->fieldName][$langcode][3]), 'Option 3 does not exist');
 
     // Completely new options appear.
-    $this->field['settings']['allowed_values'] = array(10 => 'Update', 20 => 'Twenty');
+    $this->field->settings['allowed_values'] = array(10 => 'Update', 20 => 'Twenty');
     $this->field->save();
     $form = \Drupal::entityManager()->getForm($entity);
     $this->assertTrue(empty($form[$this->fieldName][$langcode][1]), 'Option 1 does not exist');
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/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 80e8a6b..23d9ecc 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/Upgrade/FieldUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php
index dd13cf9..0d7a1fc 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php
@@ -65,7 +65,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(
@@ -104,7 +104,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/taxonomy/lib/Drupal/taxonomy/Plugin/Core/Entity/Vocabulary.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Core/Entity/Vocabulary.php
index abcb75b..d1cb810 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Core/Entity/Vocabulary.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Core/Entity/Vocabulary.php
@@ -120,8 +120,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;
@@ -161,14 +161,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/Plugin/entity_reference/selection/TermSelection.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/entity_reference/selection/TermSelection.php
index e15fbbf..06eaad3 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/entity_reference/selection/TermSelection.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/entity_reference/selection/TermSelection.php
@@ -42,7 +42,7 @@ public static function settingsForm(&$field, &$instance) {
     $form['auto_create'] = array(
       '#type' => 'checkbox',
       '#title' => t("Create referenced entities if they don't already exist"),
-      '#default_value' => $instance['settings']['handler_settings']['auto_create'],
+      '#default_value' => $instance->settings['handler_settings']['auto_create'],
     );
     return $form;
 
@@ -59,7 +59,7 @@ public function getReferenceableEntities($match = NULL, $match_operator = 'CONTA
     $options = array();
 
     $bundles = entity_get_bundles('taxonomy_term');
-    $bundle_names = !empty($this->instance['settings']['handler_settings']['target_bundles']) ? $this->instance['settings']['handler_settings']['target_bundles'] : array_keys($bundles);
+    $bundle_names = !empty($this->instance->settings['handler_settings']['target_bundles']) ? $this->instance->settings['handler_settings']['target_bundles'] : array_keys($bundles);
 
     foreach ($bundle_names as $bundle) {
       if ($vocabulary = entity_load('taxonomy_vocabulary', $bundle)) {
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 99ab62e..dd70e48 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');
@@ -516,8 +516,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();
@@ -528,7 +528,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 2167270..65c138a 100644
--- a/core/modules/taxonomy/taxonomy.module
+++ b/core/modules/taxonomy/taxonomy.module
@@ -954,7 +954,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()) {
@@ -976,9 +976,9 @@ function taxonomy_field_validate(EntityInterface $entity = NULL, $field, $instan
         }
       }
       if (!$validate) {
-        $errors[$field['field_name']][$langcode][$delta][] = array(
+        $errors[$field->id()][$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())),
         );
       }
     }
@@ -1057,7 +1057,7 @@ function taxonomy_field_settings_form($field, $instance) {
     '#tree' => TRUE,
   );
 
-  foreach ($field['settings']['allowed_values'] as $delta => $tree) {
+  foreach ($field->settings['allowed_values'] as $delta => $tree) {
     $form['allowed_values'][$delta]['vocabulary'] = array(
       '#type' => 'select',
       '#title' => t('Vocabulary'),
@@ -1146,9 +1146,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->type) 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') {
         // If a field value is not set in the node object when $node->save() is
         // called, the old value from $node->original is used.
         if (isset($node->{$field_name})) {
diff --git a/core/modules/taxonomy/taxonomy.pages.inc b/core/modules/taxonomy/taxonomy.pages.inc
index d70b8fd..593c620 100644
--- a/core/modules/taxonomy/taxonomy.pages.inc
+++ b/core/modules/taxonomy/taxonomy.pages.inc
@@ -110,7 +110,7 @@ function taxonomy_autocomplete($field_name) {
   $tags_typed = Drupal::request()->query->get('q');
 
   // Make sure the field exists and is a taxonomy field.
-  if (!($field = field_info_field($field_name)) || $field['type'] !== 'taxonomy_term_reference') {
+  if (!($field = field_info_field($field_name)) || $field->type !== 'taxonomy_term_reference') {
     // Error string. The JavaScript handler will realize this is not JSON and
     // will display it as debugging information.
     print t('Taxonomy field @field_name not found.', array('@field_name' => $field_name));
@@ -126,7 +126,7 @@ function taxonomy_autocomplete($field_name) {
 
     // Part of the criteria for the query come from the field's own settings.
     $vids = array();
-    foreach ($field['settings']['allowed_values'] as $tree) {
+    foreach ($field->settings['allowed_values'] as $tree) {
       $vids[] = $tree['vocabulary'];
     }
 
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 9a1910f..b313602 100644
--- a/core/modules/text/lib/Drupal/text/TextProcessed.php
+++ b/core/modules/text/lib/Drupal/text/TextProcessed.php
@@ -69,8 +69,8 @@ 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()) {
-      return check_markup($this->text->getValue(), $this->format->getValue(), $entity->language()->id);
+    if (!empty($instance->settings['text_processing']) && $this->format->getValue()) {
+      return check_markup($this->text->getValue(), $this->format->getValue(), $entity->language()->langcode);
     }
     else {
       // If no format is available, still make sure to sanitize the text.
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/user/lib/Drupal/user/Plugin/entity_reference/selection/UserSelection.php b/core/modules/user/lib/Drupal/user/Plugin/entity_reference/selection/UserSelection.php
index fe96ccc..004828a 100644
--- a/core/modules/user/lib/Drupal/user/Plugin/entity_reference/selection/UserSelection.php
+++ b/core/modules/user/lib/Drupal/user/Plugin/entity_reference/selection/UserSelection.php
@@ -31,7 +31,7 @@ class UserSelection extends SelectionBase {
    */
   public static function settingsForm(&$field, &$instance) {
     // Merge in default values.
-    $instance['settings']['handler_settings'] += array(
+    $instance->settings['handler_settings'] += array(
       'filter' => array(
         'type' => '_none',
       ),
@@ -47,7 +47,7 @@ public static function settingsForm(&$field, &$instance) {
       ),
       '#ajax' => TRUE,
       '#limit_validation_errors' => array(),
-      '#default_value' => $instance['settings']['handler_settings']['filter']['type'],
+      '#default_value' => $instance->settings['handler_settings']['filter']['type'],
     );
 
     $form['filter']['settings'] = array(
@@ -56,9 +56,9 @@ public static function settingsForm(&$field, &$instance) {
       '#process' => array('_entity_reference_form_process_merge_parent'),
     );
 
-    if ($instance['settings']['handler_settings']['filter']['type'] == 'role') {
+    if ($instance->settings['handler_settings']['filter']['type'] == 'role') {
       // Merge in default values.
-      $instance['settings']['handler_settings']['filter'] += array(
+      $instance->settings['handler_settings']['filter'] += array(
         'role' => NULL,
       );
 
@@ -67,7 +67,7 @@ public static function settingsForm(&$field, &$instance) {
         '#title' => t('Restrict to the selected roles'),
         '#required' => TRUE,
         '#options' => array_diff_key(user_role_names(TRUE), drupal_map_assoc(array(DRUPAL_AUTHENTICATED_RID))),
-        '#default_value' => $instance['settings']['handler_settings']['filter']['role'],
+        '#default_value' => $instance->settings['handler_settings']['filter']['role'],
       );
     }
 
@@ -132,8 +132,8 @@ public function entityQueryAlter(SelectInterface $query) {
     }
 
     // Add the filter by role option.
-    if (!empty($this->instance['settings']['handler_settings']['filter'])) {
-      $filter_settings = $this->instance['settings']['handler_settings']['filter'];
+    if (!empty($this->instance->settings['handler_settings']['filter'])) {
+      $filter_settings = $this->instance->settings['handler_settings']['filter'];
       if ($filter_settings['type'] == 'role') {
         $tables = $query->getTables();
         $base_table = $tables['base_table']['alias'];
diff --git a/core/modules/views/lib/Drupal/views/Plugin/entity_reference/selection/ViewsSelection.php b/core/modules/views/lib/Drupal/views/Plugin/entity_reference/selection/ViewsSelection.php
index e9db07e..0d19317 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/entity_reference/selection/ViewsSelection.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/entity_reference/selection/ViewsSelection.php
@@ -59,11 +59,11 @@ public function __construct(FieldDefinitionInterface $field_definition, EntityIn
    * {@inheritdoc}
    */
   public static function settingsForm(&$field, &$instance) {
-    $view_settings = empty($instance['settings']['handler_settings']['view']) ? array() : $instance['settings']['handler_settings']['view'];
+    $view_settings = empty($instance->settings['handler_settings']['view']) ? array() : $instance->settings['handler_settings']['view'];
     $displays = views_get_applicable_views('entity_reference_display');
     // Filter views that list the entity type we want, and group the separate
     // displays by view.
-    $entity_info = entity_get_info($field['settings']['target_type']);
+    $entity_info = entity_get_info($field->settings['target_type']);
     $options = array();
     foreach ($displays as $data) {
       list($view, $display_id) = $data;
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(),
