Repository: PrefectHQ/prefect

Issue:
JSON serialization of deployment fails if parameters include dictionary with non-string keys
### First check

- [X] I added a descriptive title to this issue.
- [X] I used the GitHub search to find a similar issue and didn't find it.
- [X] I searched the Prefect documentation for this issue.
- [X] I checked that this issue is related to Prefect and not one of its dependencies.

### Bug summary

If a flow deployment contains a dictionary with non-string keys as a parameter, its registration fails. The problem seems to be due to the JSON serialization of the model and occurs also if type hints are provided for the respective dictionary. I could not find any note in the documentation that dictionaries with non-string keys are not suitable for usage as flow parameters in general. Above that, I think that it should be possible to avoid this error, e. g., by using serializers with enhanced-compatibility options if non-string keys can be expected from the type hints. 

### Reproduction

```python3
from prefect import flow
from prefect.deployments import Deployment
from typing import Dict


@flow
def test_flow(dict_param: Dict[int, str]):
    for k in dict_param:
        print(dict_param[k])


flow_params = dict(dict_param={1: "a", 2: "b"})

deployment = Deployment.build_from_flow(
    flow=test_flow, name="test_deployment", parameters=flow_params
)

if __name__ == "__main__":
    deployment.apply()
```


### Error

```python3
Traceback (most recent call last):
  File "/home/tobias/CodingPlayground/Bug reproduction/prefect_dict_param_bug.py", line 19, in <module>
    deployment.apply()
  File "/home/tobias/CodingPlayground/.venv/lib/python3.8/site-packages/prefect/utilities/asyncutils.py", line 255, in coroutine_wrapper
    return call()
  File "/home/tobias/CodingPlayground/.venv/lib/python3.8/site-packages/prefect/_internal/concurrency/calls.py", line 383, in __call__
    return self.result()
  File "/home/tobias/CodingPlayground/.venv/lib/python3.8/site-packages/prefect/_internal/concurrency/calls.py", line 283, in result
    return self.future.result(timeout=timeout)
  File "/home/tobias/CodingPlayground/.venv/lib/python3.8/site-packages/prefect/_internal/concurrency/calls.py", line 169, in result
    return self.__get_result()
  File "/home/tobias/.pyenv/versions/3.8.11/lib/python3.8/concurrent/futures/_base.py", line 389, in __get_result
    raise self._exception
  File "/home/tobias/CodingPlayground/.venv/lib/python3.8/site-packages/prefect/_internal/concurrency/calls.py", line 346, in _run_async
    result = await coro
  File "/home/tobias/CodingPlayground/.venv/lib/python3.8/site-packages/prefect/deployments/deployments.py", line 714, in apply
    deployment_id = await client.create_deployment(
  File "/home/tobias/CodingPlayground/.venv/lib/python3.8/site-packages/prefect/client/orchestration.py", line 1467, in create_deployment
    json = deployment_create.dict(json_compatible=True, exclude=exclude)
  File "/home/tobias/CodingPlayground/.venv/lib/python3.8/site-packages/prefect/_internal/schemas/bases.py", line 149, in dict
    return json.loads(self.json(*args, **kwargs))
  File "/home/tobias/CodingPlayground/.venv/lib/python3.8/site-packages/prefect/_internal/schemas/bases.py", line 103, in json
    return super().json(*args, **kwargs)
  File "/home/tobias/CodingPlayground/.venv/lib/python3.8/site-packages/pydantic/main.py", line 504, in json
    return self.__config__.json_dumps(data, default=encoder, **dumps_kwargs)
  File "/home/tobias/CodingPlayground/.venv/lib/python3.8/site-packages/prefect/_internal/schemas/serializers.py", line 12, in orjson_dumps
    return orjson.dumps(v, default=default).decode()
TypeError: Dict key must be str
```


### Versions

```Text
Version:             2.10.20
API version:         0.8.4
Python version:      3.8.11
Git commit:          08326f42
Built:               Fri, Jul 7, 2023 3:22 PM
OS/Arch:             linux/x86_64
Profile:             default
Server type:         ephemeral
Server:
  Database:          sqlite
  SQLite version:    3.37.2
```


### Additional context

_No response_


Discussion:
Thanks for bringing this to our attention @tgnade, we'll look into it.

Resolving patch:
diff --git a/src/prefect/_internal/schemas/bases.py b/src/prefect/_internal/schemas/bases.py
--- a/src/prefect/_internal/schemas/bases.py
+++ b/src/prefect/_internal/schemas/bases.py
@@ -17,7 +17,7 @@
 
 from prefect._internal.compatibility.experimental import experiment_enabled
 from prefect._internal.schemas.fields import DateTimeTZ
-from prefect._internal.schemas.serializers import orjson_dumps
+from prefect._internal.schemas.serializers import orjson_dumps_extra_compatible
 
 T = TypeVar("T")
 
@@ -60,7 +60,7 @@ class Config:
 
         # Use orjson for serialization
         json_loads = orjson.loads
-        json_dumps = orjson_dumps
+        json_dumps = orjson_dumps_extra_compatible
 
     def _reset_fields(self) -> Set[str]:
         """A set of field names that are reset when the PrefectBaseModel is copied.


Test patch:
diff --git a/tests/fixtures/client.py b/tests/fixtures/client.py
--- a/tests/fixtures/client.py
+++ b/tests/fixtures/client.py
@@ -1,3 +1,5 @@
+from typing import Dict
+
 import pytest
 
 from prefect import flow
@@ -27,6 +29,17 @@ def client_test_flow(param=1):
     return client_test_flow
 
 
+@pytest.fixture(scope="session")
+def flow_function_dict_parameter():
+    @flow(
+        version="test", description="A test function with a dictionary as a parameter"
+    )
+    def client_test_flow_dict_parameter(dict_param: Dict[int, str]):
+        return dict_param
+
+    return client_test_flow_dict_parameter
+
+
 @pytest.fixture(scope="module")
 def test_block():
     class x(Block):
diff --git a/tests/test_deployments.py b/tests/test_deployments.py
--- a/tests/test_deployments.py
+++ b/tests/test_deployments.py
@@ -689,6 +689,23 @@ async def test_deployment_apply_syncs_triggers(
                     create_route.calls[0].request.content
                 ) == trigger.as_automation().dict(json_compatible=True)
 
+    async def test_deployment_apply_with_dict_parameter(
+        self, flow_function_dict_parameter, prefect_client
+    ):
+        d = await Deployment.build_from_flow(
+            flow_function_dict_parameter,
+            name="foo",
+            parameters=dict(dict_param={1: "a", 2: "b"}),
+        )
+
+        assert d.flow_name == flow_function_dict_parameter.name
+        assert d.name == "foo"
+
+        dep_id = await d.apply()
+        dep = await prefect_client.read_deployment(dep_id)
+
+        assert dep is not None
+
 
 class TestRunDeployment:
     @pytest.mark.parametrize(