Set default values according to JSON schema automatically
Asked Answered
A

3

6

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:

  1. Is the 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.

  1. I would like to have a method that transforms my 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!

Additament answered 28/4, 2022 at 13:45 Comment(0)
C
4

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]  
Cohesive answered 11/5, 2022 at 20:23 Comment(4)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Barium
AFAICS this package just creates a new JSON with the given schema defaults. Nevertheless I want a possibility to fill up a JSON where default values are missing. On the other hand, given values are not supposed to be overwritten ...Additament
You're right.. I misread your question. What you can do is to generate the default object using jsonschema_default package and then use the default JSON object to fill in the missing key in your json_dictCohesive
I edited my original postCohesive
H
3

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.

Heterogeneity answered 28/4, 2022 at 17:33 Comment(1)
Ok, thank you. That is what I suspected. Would it be worth to build a package which addresses point 2 of my question?Additament
N
2

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)
Nickels answered 14/7, 2023 at 10:6 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.