Instead of setting defaults during validation, have you considered first filling all defaults in an instance and then validating it?
You can use `fill_default` from [`jsonschema-fill-default`](https://pypi.org/project/jsonschema-fill-default/) to fill all missing defaults in an existing instance with its schema:
```command
pip install jsonschema-fill-default
```
```python
from jsonschema_fill_default import fill_default
schema = {
"type": "object",
"properties": {
"key_1": {},
"key_2": {
"type": "string",
"default": "do_not_overwrite_if_key_exists",
},
"key_3": {
"type": "string",
"default": "use_it_if_key_does_not_exist",
},
},
"required": ["key_1"],
}
json_dict = {"key_1": "key_1_value", "key_2": "key_2_value"}
fill_default(json_dict, schema) # Mutates instance!
```
```command
>>> json_dict
{"key_1": "key_1_value", "key_2": "key_2_value", "key_3": "use_it_if_key_does_not_exist"}
```
The function you show only fills defaults in "properties", whereas `fill_default` works with all nested combinations of `"properties"`, `"allOf"`, `"anyOf"`, `"oneOf"`, `"dependentSchemas"`, `"if-then(-else)"`, `"prefixItems"`, and `"items"` keywords of [Draft 2020-12](https://json-schema.org/draft/2020-12) [JSON Schema](https://json-schema.org/).
You can use `fill_default` from [`jsonschema-fill-default`](https://pypi.org/project/jsonschema-fill-default/) to fill all missing defaults in an existing instance with its schema:
```command
pip install jsonschema-fill-default
```
```python
from jsonschema_fill_default import fill_default
schema = {
"type": "object",
"properties": {
"key_1": {},
"key_2": {
"type": "string",
"default": "do_not_overwrite_if_key_exists",
},
"key_3": {
"type": "string",
"default": "use_it_if_key_does_not_exist",
},
},
"required": ["key_1"],
}
json_dict = {"key_1": "key_1_value", "key_2": "key_2_value"}
fill_default(json_dict, schema) # Mutates instance!
```
```command
>>> json_dict
{"key_1": "key_1_value", "key_2": "key_2_value", "key_3": "use_it_if_key_does_not_exist"}
```
I created `jsonschema-fill-default` with Tom-tbt's answer as inspiration for `fill_default`.
The filling is done recursively for all missing and nested defaults. It works with all combinations of `"properties"`, `"allOf"`, `"anyOf"`, `"oneOf"`, `"dependentSchemas"`, `"if-then(-else)"`, `"prefixItems"`, and `"items"` keywords.
Note:
- The instance must already be valid to its schema.
- The schema itself must be a valid [Draft 2020-12](https://json-schema.org/draft/2020-12) [JSON Schema](https://json-schema.org/).
- The filled instance is **not automatically validated**.
See [Examples](https://github.com/larsmaxfield/jsonschema-fill-default#examples) on the project's GitHub for details.