Reputation: 317
I am using the jsonschema
package in python
to validate my JSONs. I can set default
in jsonschema
. Let us assume the following schema:
from jsonschema import validate
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"}
validate(json_dict, schema)
My json_dict
is perfectly valid. I have two questions:
default
keyword really so "useless" as the documentation (see below) says? This is all you get?The “default” keyword doesn’t have an effect, but is nice to include for readers of the schema to more easily recognize the default behavior.
json_dict
into the following according to the default
keyword. Do you know of such a package?json_dict = {"key_1": "key_1_value", "key_2": "key_2_value", "key_3": "use_it_if_key_does_not_exist"}
Thanks!
Upvotes: 8
Views: 5667
Reputation: 2267
This is now possible with jsonschema-default>=1.8.0
import jsonschema_default
obj = {}
default_obj = jsonschema_default.fill_from(schema="<schema>", target=obj)
Upvotes: 0
Reputation: 53
You can use fill_default
from jsonschema-fill-default
to fill all missing defaults in an existing instance with its schema:
pip install jsonschema-fill-default
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!
>>> 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:
See Examples on the project's GitHub for details.
Upvotes: 0
Reputation: 31
The jsonschema_default solution from @ajack wouldn't work with partially filled nested objects: The key would exist thus missing default values would not be added.
Say I have this default:
{
"foo": {
"bar_1": "value_1",
"bar_2": "value_2"
},
"other": "something"
}
And provide this json:
{
"foo": {
"bar_1": "value_1"
}
}
Then only "other"
would be added with the default value. "bar_2"
wouldn't be added because "foo"
exists.
One solution with recursion is to search all nested structures with defaults to fill. This is my attempt of a solution:
def fill_default(json_dict, schema):
for key in schema["properties"]:
if "properties" in schema["properties"][key].keys(): # Recursion
if key not in json_dict.keys():
json_dict[key] = fill_default(dict(), schema["properties"][key])
else:
json_dict[key] = fill_default(json_dict[key], schema["properties"][key])
if len(json_dict[key]) == 0: #No default found inside
del json_dict[key]
elif key not in json_dict.keys() and "default" in schema["properties"][key].keys():
json_dict[key] = schema["properties"][key]["default"]
return json_dict
json_dict = fill_default(json_dict, schema)
Upvotes: 3
Reputation: 61
You can use the jsonschema_default
package linked below to generate a default JSON object from your JSON schema.
https://pypi.org/project/jsonschema-default/
Then you can use the default JSON object to fill in the missing key in your json_dict
Like so:
import jsonschema_default as jd
default_obj = jd.create_from("./data_schema_example.json")
for key in default_obj.keys():
if key not in json_dict:
json_dict[key] = default_obj[key]
Upvotes: 6
Reputation: 53996
The default
keyword is documented here: https://json-schema.org/draft/2020-12/json-schema-validation.html#rfc.section.9.2
It is indeed not a validation keyword, and only acts as an annotation. It is up to individual applications to decide how to use this annotation when it is generated from schema evaluation.
Upvotes: 3