### Apache Airflow version

2.7.1

### What happened

120 DAGs broke when I updated to Airflow 2.7.1. I had to revert to 2.7.0 again, so the tests below are from a local deployment.

The error message is the same for all DAGs:

```python
Broken DAG: [/opt/airflow/dags/dag-name.py] Traceback (most recent call last):
  File "/home/airflow/.local/lib/python3.11/site-packages/airflow/models/dag.py", line 640, in __init__
    self.validate_schedule_and_params()
  File "/home/airflow/.local/lib/python3.11/site-packages/airflow/models/dag.py", line 3289, in validate_schedule_and_params
    raise AirflowException(
airflow.exceptions.AirflowException: DAG Schedule must be None, if there are any required params without default values
```

After testing, I found that if I change the blob_prefix param to "" instead of None, the DAG imports successfully. I have various other params which are None that I will probably need to assign default values for (in reality, the function which Airflow runs handles cases if the value is None, but I guess I need to add a default in the DAG). All 120 DAGs with errors had a field like this in the "params" dictionary I pass to Airflow params.

```python
params = {
    "exclude_pattern": "*errors*",
    "blob_prefix": None,
```

### What you think should happen instead

These are legacy DAGs which have run for a long time without changes (old Airflow instance), so I did not expect an upgrade to break them. 

### How to reproduce

I believe the root cause is passing a param with the value None to the DAG params:

```python
params = {
  subfolder=None,
  conn_id="gcs_conn_id",
}

@dag(
    dag_id="dag-example",
    start_date=datetime(2023, 2, 2, tz="America/New_York"),
    schedule="41 2 * * *",
    params=params,
)
```

### Operating System

Ubuntu 22.04

### Versions of Apache Airflow Providers

Providers info
apache-airflow-providers-celery          | 3.3.3 
apache-airflow-providers-common-sql      | 1.7.1 
apache-airflow-providers-docker          | 3.7.4 
apache-airflow-providers-ftp             | 3.5.1 
apache-airflow-providers-google          | 10.7.0
apache-airflow-providers-http            | 4.5.1 
apache-airflow-providers-imap            | 3.3.1 
apache-airflow-providers-microsoft-azure | 6.3.0 
apache-airflow-providers-mysql           | 5.3.0 
apache-airflow-providers-odbc            | 4.0.0 
apache-airflow-providers-openlineage     | 1.0.2 
apache-airflow-providers-postgres        | 5.6.0 
apache-airflow-providers-redis           | 3.3.1 
apache-airflow-providers-sftp            | 4.6.0 
apache-airflow-providers-sqlite          | 3.4.3 
apache-airflow-providers-ssh             | 3.7.2 

### Deployment

Other Docker-based deployment

### Deployment details

Docker Swarm using docker stack deploy

### Anything else

DAGs fail to import when deployed on 2.7.1

### Are you willing to submit PR?

- [ ] Yes I am willing to submit a PR!

### Code of Conduct

- [X] I agree to follow this project's [Code of Conduct](https://github.com/apache/airflow/blob/main/CODE_OF_CONDUCT.md)

are merged into the new *schedule* argument.
    :param dag_id: The id of the DAG; must consist exclusively of alphanumeric
        characters, dashes, dots and underscores (all ASCII)
    :param description: The description for the DAG to e.g. be shown on the webserver
    :param schedule: Defines the rules according to which DAG runs are scheduled. Can
        accept cron string, timedelta object, Timetable, or list of Dataset objects.
        See also :doc:`/howto/timetable`.
    :param start_date: The timestamp from which the scheduler will
        attempt to backfill
    :param end_date: A date beyond which your DAG won't run, leave to None
        for open-ended scheduling
    :param template_searchpath: This list of folders (non-relative)
        defines where jinja will look for your templates. Order matters.
        Note that jinja/airflow includes the path of your DAG file by
        default
    :param template_undefined: Template undefined type.
    :param user_defined_macros: a dictionary of macros that will be exposed
        in your jinja templates. For example, passing ``dict(foo='bar')``
        to this argument allows you to ``{{ foo }}`` in all jinja
        templates related to this DAG. Note that you can pass any
        type of object here.
    :param user_defined_filters: a dictionary of filters that will be exposed
        in your jinja templates. For example, passing
        ``dict(hello=lambda name: 'Hello %s' % name)`` to this argument allows
        you to ``{{ 'world' | hello }}`` in all jinja templates related to
        this DAG.
    :param default_args: A dictionary of default parameters to be used
        as constructor keyword parameters when initialising operators.
        Note that operators have the same hook, and precede those defined
        here, meaning that if your dict contains `'depends_on_past': True`