Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to handle default values of sub-objects within a JSON schema validator? #200

Closed
pboettch opened this issue Dec 20, 2016 · 8 comments
Closed

Comments

@pboettch
Copy link

pboettch commented Dec 20, 2016

I asked this question on StackOverflow before realising that it might be better placed here:

How should a JSON schema validator handle the case where a sub-object of an object has a default value but the parent object hasn't?

Imagine the following schema

{
    "type": "object",
    "properties": {
        "element": {
		   "type": "object",
		   "properties": {
			   "number" : { "type": "integer", "default": 15 }
		   }
		}
    }
}

Validated against the following JSON: {} is resulting in {}.

But shouldn't it result in

{
    "element": {
        "number": 15
    }
}

.

How do we have to interpret the default-keyword? I read the corresponding lines in the standard, but they haven't helped me further.

The same applies to the required-list in sub-objects.

@handrews
Copy link
Contributor

A default is something you can use, but validation does not automatically write the default into the instance.

The usage of default seems to be a topic of some debate still, so someone else may come along and answer this differently. Most people seem to talk only in terms of pre-populating UI forms. Since I work on APIs more than UIs, I tend to think of it in the following terms:

  • In an API request, a default could mean that the server will treat a missing value as if it were the default.
  • In an API response, the client may fill in the default value, possibly before passing the instance to non-interactive application code (if it's interactive, see the UI case mentioned above).

But in all cases the exact usage of default is determined by the application, not the simple act of validations. In the UI it tends to be pre-population, before user input. In an API it tends to be post-data-input, when the input does not include the field.

Getting back to your actual question, I would read that schema as only allowing a default to be used (however it is used) for the "number" field if the "element" object is present. In order to get the post-default-filling-in behavior that you want, you'd need something like:

{
    "type": "object",
    "properties": {
        "element": {
            "type": "object",
            "properties": {
                "number" : {"type": "integer", "default": 15}
            },
            "default": {"element": {"number": 15}}
        }
    }
}

or possibly

{
    "type": "object",
    "properties": {
        "element": {
            "type": "object",
            "properties": {
                "number" : {"type": "integer", "default": 15}
            },
            "default": {"element": {}}
        }
    }
}

which I guess could mean "put in 'element' with an empty object, and since within the 'element' object there is a default 'number' of 15" although honestly that's making my head hurt a bit.

This would be a good thing to put on the web site to explain defaults.

@pboettch
Copy link
Author

pboettch commented Dec 20, 2016

If the origin of the existence default-field in schemas is related to UI-descriptions then I understand why validators are not filling it in. Well, mine is actually (not yet published).

I started using JSON and JSON schema literally yesterday.

My use of it is for configuration-files. Validating config-files with a schema and filling in default-values and handling the required-array in a recursive way will simplify a lot the code actually using the config-file.

Maybe a schema should not be valid if a sub-object has a default value but the parent one has not.

Maybe it is a little bit early to put things on a website. I guess it needs more opinions as you say.

@Relequestual
Copy link
Member

Welcome @pboettch - Great to see new faces getting involved.

Souns like you have a good use case. I totally see what you are saying with default. I believe there's a fair bit of discussion about it already. Feel free to poke about existing and past issues and PRs as you have time, if you want. Lot to do...

@handrews
Copy link
Contributor

Maybe a schema should not be valid if a sub-object has a default value but the parent one has not.

@pboettch there are valid reasons to want to allow this. You may not automatically want there to be an "element" member, but if it is explicitly there, you may want its "number" member to have a particular default. Requiring defaults all the way down would put a lot of restrictions on valid use cases.

Additionally, we try to keep schema validation keywords context-free, meaning their behavior in a given schema is independent of parent or child schemas. The core keywords ($schema, id/$id, $ref) are not context-free (the meta-schema and base URI are inherited by child schemas), but the actual validation keywords are.

@epoberezkin
Copy link
Member

@pboettch Welcome. I think the idea of default is the following: "if the property is absent, it can be replaced with the default value". Or "considered present with the default value" as some would say.

The spec doesn't define how validators should treat this keyword. Some validators provide an option to modify data using these defaults. It is up to a validator's author to define whether a "deep" default should only be used if the parent object is present, or if if it should create a parent object if it is absent. You can even support both behaviours by providing some "deepDefaults" option...

But I don't think it is reasonable to want the spec to require that a parent schema has default if a child schema does. As @handrews wrote it violates design principles of JSON schema ("context-free") and also there are cases when it is undesirable.

@handrews
Copy link
Contributor

It is up to a validator's author to define whether a "deep" default should only be used if the parent object is present, or if if it should create a parent object if it is absent.

I'm pretty sure that is not the intended behavior (creating parent objects to reach a deep default). That would violate the independence of schemas- aside from needing all children to validate in order to get the overall validation results, child schemas never impact parent schemas, and this would be like changing the parent to have a default.

@pboettch
Copy link
Author

In my validator, I decided to add a method to generate an empty document, based on the default values. I'm thinking about even adding empty required fields to it.

I agree, this has nothing to do with the standard and a validator should not modify the document. But for my use-case for the moment I think this is necessary.

@epoberezkin
Copy link
Member

epoberezkin commented Dec 28, 2016

I agree, this has nothing to do with the standard

@pboettch Should we close it then?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants