Repository: pydantic/pydantic

Issue:
`schema_json` can't encode default value of`dict[UUID, Any]` and raises `TypeError`
### Initial Checks

- [X] I have searched GitHub for a duplicate issue and I'm sure this is something new
- [X] I have searched Google & StackOverflow for a solution and couldn't find anything
- [X] I have read and followed [the docs](https://pydantic-docs.helpmanual.io) and still think this is a bug
- [X] I am confident that the issue is with pydantic (not my code, or another library in the ecosystem like [FastAPI](https://fastapi.tiangolo.com) or [mypy](https://mypy.readthedocs.io/en/stable))


### Description

When a model has default value of `{uuid4(): "..."}`, and being a dafault value of another model, `json_schema` fails to generate schema with an error.

### Example Code

```Python
from uuid import uuid4

from pydantic import BaseModel
from pydantic import UUID4


class Service(BaseModel):
    urls: dict[UUID4, str] = {uuid4(): "https://example.com"}


class Settings(BaseModel):
    service: Service = Service()


print(Settings.schema_json(indent=4, ensure_ascii=False))
```

```py
Traceback (most recent call last):
  File "/Users/bobronium/Library/Application Support/JetBrains/PyCharm2022.3/scratches/scratch_131.py", line 15, in <module>
    print(Settings.schema_json(indent=4, ensure_ascii=False))
  File "pydantic/main.py", line 674, in pydantic.main.BaseModel.schema_json
  File "/Users/bobronium/.pyenv/versions/3.10.1/lib/python3.10/json/__init__.py", line 238, in dumps
    **kw).encode(obj)
  File "/Users/bobronium/.pyenv/versions/3.10.1/lib/python3.10/json/encoder.py", line 201, in encode
    chunks = list(chunks)
  File "/Users/bobronium/.pyenv/versions/3.10.1/lib/python3.10/json/encoder.py", line 431, in _iterencode
    yield from _iterencode_dict(o, _current_indent_level)
  File "/Users/bobronium/.pyenv/versions/3.10.1/lib/python3.10/json/encoder.py", line 405, in _iterencode_dict
    yield from chunks
  File "/Users/bobronium/.pyenv/versions/3.10.1/lib/python3.10/json/encoder.py", line 405, in _iterencode_dict
    yield from chunks
  File "/Users/bobronium/.pyenv/versions/3.10.1/lib/python3.10/json/encoder.py", line 405, in _iterencode_dict
    yield from chunks
  [Previous line repeated 1 more time]
  File "/Users/bobronium/.pyenv/versions/3.10.1/lib/python3.10/json/encoder.py", line 376, in _iterencode_dict
    raise TypeError(f'keys must be str, int, float, bool or None, '
TypeError: keys must be str, int, float, bool or None, not UUID
```

### This works, though

```py
from uuid import uuid4

from pydantic import BaseModel
from pydantic import UUID4


class Service(BaseModel):
    urls: dict[UUID4, str] = {uuid4(): "https://example.com"}


class Settings(BaseModel):
    service: Service  # <--------- Notice no default value here


print(Settings.schema_json(indent=4, ensure_ascii=False))
```
<details>

```json
{
    "title": "Settings",
    "type": "object",
    "properties": {
        "service": {
            "$ref": "#/definitions/Service"
        }
    },
    "required": [
        "service"
    ],
    "definitions": {
        "Service": {
            "title": "Service",
            "type": "object",
            "properties": {
                "urls": {
                    "title": "Urls",
                    "default": {
                        "ac762f77-1e77-4ff8-906a-fd63ca622938": "https://example.com"
                    },
                    "type": "object",
                    "additionalProperties": {
                        "type": "string"
                    }
                }
            }
        }
    }
}
```

</details>

### Python, Pydantic & OS Version

```Text
pydantic version: 1.10.2
            pydantic compiled: True
                 install path: .venv/lib/python3.10/site-packages/pydantic
               python version: 3.10.1 (main, Jan 31 2022, 09:16:52) [Clang 13.0.0 (clang-1300.0.29.3)]
                     platform: macOS-12.4-arm64-arm-64bit
     optional deps. installed: ['dotenv', 'typing-extensions']
```


### Affected Components

- [ ] [Compatibility between releases](https://pydantic-docs.helpmanual.io/changelog/)
- [ ] [Data validation/parsing](https://pydantic-docs.helpmanual.io/usage/models/#basic-model-usage)
- [ ] [Data serialization](https://pydantic-docs.helpmanual.io/usage/exporting_models/) - `.dict()` and `.json()`
- [X] [JSON Schema](https://pydantic-docs.helpmanual.io/usage/schema/)
- [ ] [Dataclasses](https://pydantic-docs.helpmanual.io/usage/dataclasses/)
- [ ] [Model Config](https://pydantic-docs.helpmanual.io/usage/model_config/)
- [ ] [Field Types](https://pydantic-docs.helpmanual.io/usage/types/) - adding or changing a particular data type
- [ ] [Function validation decorator](https://pydantic-docs.helpmanual.io/usage/validation_decorator/)
- [ ] [Generic Models](https://pydantic-docs.helpmanual.io/usage/models/#generic-models)
- [ ] [Other Model behaviour](https://pydantic-docs.helpmanual.io/usage/models/) - `construct()`, pickling, private attributes, ORM mode
- [ ] [Plugins](https://pydantic-docs.helpmanual.io/) and integration with other tools - mypy, FastAPI, python-devtools, Hypothesis, VS Code, PyCharm, etc.


Comments:
Thanks for reporting, if there's an easy fix, happy to accept a PR for 1.10.3.

Otherwise, let's make sure we get this right in v2. Tbh, there are lots of types that currently break JsonSchema. 

Patch:
diff --git a/pydantic/schema.py b/pydantic/schema.py
--- a/pydantic/schema.py
+++ b/pydantic/schema.py
@@ -1,6 +1,7 @@
 import re
 import warnings
 from collections import defaultdict
+from dataclasses import is_dataclass
 from datetime import date, datetime, time, timedelta
 from decimal import Decimal
 from enum import Enum
@@ -971,7 +972,14 @@ def multitypes_literal_field_for_schema(values: Tuple[Any, ...], field: ModelFie
 
 
 def encode_default(dft: Any) -> Any:
-    if isinstance(dft, Enum):
+    from .main import BaseModel
+
+    if isinstance(dft, BaseModel) or is_dataclass(dft):
+        dft = cast('dict[str, Any]', pydantic_encoder(dft))
+
+    if isinstance(dft, dict):
+        return {encode_default(k): encode_default(v) for k, v in dft.items()}
+    elif isinstance(dft, Enum):
         return dft.value
     elif isinstance(dft, (int, float, str)):
         return dft
@@ -979,8 +987,6 @@ def encode_default(dft: Any) -> Any:
         t = dft.__class__
         seq_args = (encode_default(v) for v in dft)
         return t(*seq_args) if is_namedtuple(t) else t(seq_args)
-    elif isinstance(dft, dict):
-        return {encode_default(k): encode_default(v) for k, v in dft.items()}
     elif dft is None:
         return None
     else:


Test patch:
diff --git a/tests/test_schema.py b/tests/test_schema.py
--- a/tests/test_schema.py
+++ b/tests/test_schema.py
@@ -1523,6 +1523,38 @@ class UserModel(BaseModel):
     }
 
 
+def test_model_default():
+    """Make sure inner model types are encoded properly"""
+
+    class Inner(BaseModel):
+        a: Dict[Path, str] = {Path(): ''}
+
+    class Outer(BaseModel):
+        inner: Inner = Inner()
+
+    assert Outer.schema() == {
+        'definitions': {
+            'Inner': {
+                'properties': {
+                    'a': {
+                        'additionalProperties': {'type': 'string'},
+                        'default': {'.': ''},
+                        'title': 'A',
+                        'type': 'object',
+                    }
+                },
+                'title': 'Inner',
+                'type': 'object',
+            }
+        },
+        'properties': {
+            'inner': {'allOf': [{'$ref': '#/definitions/Inner'}], 'default': {'a': {'.': ''}}, 'title': 'Inner'}
+        },
+        'title': 'Outer',
+        'type': 'object',
+    }
+
+
 @pytest.mark.parametrize(
     'kwargs,type_,expected_extra',
     [