Index: src/wp-includes/meta.php
===================================================================
--- src/wp-includes/meta.php	(revision 43384)
+++ src/wp-includes/meta.php	(working copy)
@@ -532,12 +532,12 @@
 			return array_map( 'maybe_unserialize', $meta_cache[ $meta_key ] );
 		}
 	}
-
-	if ( $single ) {
-		return '';
-	} else {
-		return array();
+	$object_subtype = get_object_subtype( $meta_type, $object_id );
+	$default        = get_metadata_default( $meta_type, $meta_key, $object_subtype );
+	if ( ! $single ) {
+		$default_value = (array) $default_value;
 	}
+	return $default;
 }
 
 /**
@@ -1045,6 +1045,7 @@
  *                                     Valid values are 'string', 'boolean', 'integer', and 'number'.
  *     @type string $description       A description of the data attached to this meta key.
  *     @type bool   $single            Whether the meta key has one value per object, or an array of values per object.
+ *     @type mixed  $default           Optional. Default value to return if the meta key does not exist.
  *     @type string $sanitize_callback A function or method to call when sanitizing `$meta_key` data.
  *     @type string $auth_callback     Optional. A function or method to call when performing edit_post_meta, add_post_meta, and delete_post_meta capability checks.
  *     @type bool   $show_in_rest      Whether data associated with this meta key can be considered public.
@@ -1070,6 +1071,7 @@
 		'sanitize_callback' => null,
 		'auth_callback'     => null,
 		'show_in_rest'      => false,
+		'default'           => null,
 	);
 
 	// There used to be individual args for sanitize and auth callbacks
@@ -1132,6 +1134,14 @@
 		}
 	}
 
+	if ( null !== $args['default'] ) {
+		if ( ! empty( $object_subtype ) ) {
+			add_filter( "default_{$object_type}_meta_{$meta_key}_for_{$object_subtype}", 'filter_default_meta', 10, 4 );
+		} else {
+			add_filter( "default_{$object_type}_meta_{$meta_key}", 'filter_default_meta', 10, 4 );
+		}
+	}
+
 	// Global registry only contains meta keys registered with the array of arguments added in 4.6.0.
 	if ( ! $has_old_auth_cb && ! $has_old_sanitize_cb ) {
 		unset( $args['object_subtype'] );
@@ -1145,6 +1155,55 @@
 }
 
 /**
+ * Sanitize meta value.
+ *
+ * @since 3.1.3
+ * @since 5.0.0 The `$object_subtype` parameter was added.
+ *
+ * @param string $meta_key       Meta key.
+ * @param mixed  $meta_value     Meta value to sanitize.
+ * @param string $object_type    Type of object the meta is registered to.
+ *
+ * @return mixed Default Value $default_value.
+ */
+function get_metadata_default( $meta_key, $object_type, $object_subtype = '' ) {
+
+	$default_value = '';
+	if ( ! empty( $object_subtype ) && has_filter( "sanitize_{$object_type}_meta_{$meta_key}_for_{$object_subtype}" ) ) {
+
+		/**
+		 *
+		 * The dynamic portions of the hook name, `$object_type`, `$meta_key`,
+		 * and `$object_subtype`, refer to the metadata object type (comment, post, term or user),
+		 * the meta key value, and the object subtype respectively.
+		 *
+		 * @since 5.0.0
+		 *
+		 * @param mixed  $default_value  Default value.
+		 * @param string $meta_key       Meta key.
+		 * @param string $object_type    Object type.
+		 * @param string $object_subtype Object subtype.
+		 */
+		return apply_filters( "default_{$object_type}_meta_{$meta_key}_for_{$object_subtype}", $default_value, $meta_key, $object_type, $object_subtype );
+	}
+
+	/**
+	 *
+	 * The dynamic portions of the hook name, `$meta_type`, and `$meta_key`,
+	 * refer to the metadata object type (comment, post, or user) and the meta
+	 * key value, respectively.
+	 *
+	 * @since 5.5.0
+	 *
+	 * @param mixed  $default_value      Default value.
+	 * @param string $meta_key        Meta key.
+	 * @param string $object_type     Object type.
+	 * @param string $object_subtype Object subtype.
+	 */
+	return apply_filters( "default_{$object_type}_meta_{$meta_key}", $default_value, $meta_key, $object_type );
+}
+
+/**
  * Checks if a meta key is registered.
  *
  * @since 4.6.0
@@ -1199,6 +1258,14 @@
 		}
 	}
 
+	if ( isset( $args['default'] ) && null !== $args['default'] ) {
+		if ( ! empty( $object_subtype ) ) {
+			remove_filter( "default_{$object_type}_meta_{$meta_key}_for_{$object_subtype}", 'filter_default_meta' );
+		} else {
+			remove_filter( "default_{$object_type}_meta_{$meta_key}", 'filter_default_meta' );
+		}
+	}
+
 	unset( $wp_meta_keys[ $object_type ][ $object_subtype ][ $meta_key ] );
 
 	// Do some clean up
@@ -1360,3 +1427,27 @@
 	 */
 	return apply_filters( "get_object_subtype_{$object_type}", $object_subtype, $object_id );
 }
+
+/**
+ * @param $default_value
+ * @param $meta_key
+ * @param $object_type
+ * @param string $object_subtype
+ *
+ * @return mixed
+ */
+function filter_default_meta( $default_value, $meta_key, $object_type, $object_subtype = '' ) {
+	global $wp_meta_keys;
+
+	if ( ! is_array( $wp_meta_keys ) ) {
+		$wp_meta_keys = [];
+	}
+
+
+	if ( isset( $wp_meta_keys[ $object_type ][ $object_subtype ][ $meta_key ]['default'] ) &&
+	     null !== $wp_meta_keys[ $object_type ][ $object_subtype ][ $meta_key ]['default'] ) {
+		$default_value = $wp_meta_keys[ $object_type ][ $object_subtype ][ $meta_key ]['default'];
+	}
+
+	return $default_value;
+}
\ No newline at end of file
