ajv-validator / ajv

The fastest JSON schema Validator. Supports JSON Schema draft-04/06/07/2019-09/2020-12 and JSON Type Definition (RFC8927)
https://ajv.js.org
MIT License
13.84k stars 878 forks source link

Does not pick up default value if defined in $ref definition #337

Open onury opened 8 years ago

onury commented 8 years ago

What version of Ajv are you using? Does the issue happen if you use the latest version? 4.8.2

Ajv options object (see https://github.com/epoberezkin/ajv#options):

{
    allErrors: true,
    format: 'full',
    useDefaults: true
}

JSON Schema (please make it as small as possible to reproduce the issue):

{
    ...
    "properties": {
        "phone": {
            "$ref": "#/definitions/optionalPhone"
        },
       ...
    },
    "definitions": {
        "emptyString": {
            "type": "string",
            "maxLength": 0
        },
        "optionalPhone": {
            "anyOf": [
                { "format": "phone" },
                { "$ref": "#/definitions/emptyString" }
            ],
            "default": ""
        }
    }
}

Above will work only if I define default: "" within phone.

Data (please make it as small as posssible to reproduce the issue):

{}

Validation result, data AFTER validation, error messages: Data after validation: {}
No errors. Just the default value is not set for phone.

What results did you expect? { phone: "" }

epoberezkin commented 8 years ago

Yes, only from items and properties directly at the moment. It's a documented limitation: https://github.com/epoberezkin/ajv#assigning-defaults

dinvlad commented 7 years ago

Are there plans to apply defaults from references as well?

epoberezkin commented 7 years ago

I see it as "nice to have" rather than something many users need. And it's quite complex. So there are no plans to implement it at the moment.

epoberezkin commented 7 years ago

Even if you define properties in $refs, you can still define default values for the properties alongside $refs rather than inside: https://runkit.com/esp/5942f60cc72ffe0012805f9c

dinvlad commented 7 years ago

Thanks, I've tried that before but incorrectly (through allOf), which is why it wasn't working. IMO that's actually better than through Definitions.

epoberezkin commented 7 years ago

through allOf it also works (unless you put default inside allOf). And it's not that putting default inside allOf is incorrect, it's just unsupported...

dinvlad commented 7 years ago

Yep, that's exactly what I've tried. Thanks again - I think it's even cleaner without allOf.

marshall007 commented 6 years ago

@epoberezkin this seems especially bad in the case of $merge (see https://github.com/epoberezkin/ajv-merge-patch/issues/16). I was attempting to use ajv-merge-patch to avoid the subtleties in using $ref with things like additionalProperties and default. It was working great until I realized that default values weren't being applied.

Can you explain why this is still an issue when using $merge/$patch? My assumption was that the internal representation would be flatly merged (and thus the default and dynamicDefaults keywords would behave as expected).

Example Schema ```js { $id: 'activities.create', $merge: { source: { $ref: 'base.create', }, with: { type: 'object', required: [ 'entitySubType', 'name', 'endDateTime', 'startDateTime', ], additionalProperties: false, properties: { attributes: { type: 'object', default: {}, }, entityType: { type: 'string', const: EntityType.ACTIVITY, default: EntityType.ACTIVITY, }, entitySubType: { $ref: 'types#/definitions/activityType', }, name: { type: 'string' }, endDateTime: { type: 'string', format: 'date-time', }, startDateTime: { type: 'string', format: 'date-time', }, }, }, }, } ```

In the above schema, neither the defaults from the referenced base.create schema nor the with block are applied.

epoberezkin commented 6 years ago

@marshall007 This question belongs in ajv-merge-patch. $merge is implemented as a custom keyword, it doesn't merge anything into the original schema. I don't plan to improve it until json-schema-org standardises it (or some other re-use mechanism).

nick4fake commented 4 years ago

@epoberezkin are there any workarounds for oneOf/allOf? It really limits some of our cases

tobad357 commented 3 years ago

As a small note on a use case. We have a scenario where users build their schema but use a number of building blocks (address, user etc). When pulling in those building blocks the users would expect smart defaults to be applied.

Currently it seams like the only solution for us would be to resolve the refs our selves and inline them to get the expected behavior?

epoberezkin commented 3 years ago

@nick4fake: check the newly added support for discriminator keyword - it would apply default from the chosen oneOf branch.

@tobad357: you could compose JS objects so it is all just one big schema

albanm commented 1 year ago

I just struggled with this problem before finding this issue. I might be wrong, but I think this limitation is missing from the documentation. It is neither here nor here.