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

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

Open
onury opened this issue Nov 7, 2016 · 13 comments
Open

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

onury opened this issue Nov 7, 2016 · 13 comments

Comments

@onury
Copy link

onury commented Nov 7, 2016

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
Copy link
Member

epoberezkin commented Nov 7, 2016

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

@dinvlad
Copy link

dinvlad commented Jun 15, 2017

Are there plans to apply defaults from references as well?

@epoberezkin
Copy link
Member

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
Copy link
Member

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
Copy link

dinvlad commented Jun 15, 2017

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
Copy link
Member

epoberezkin commented Jun 15, 2017

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
Copy link

dinvlad commented Jun 15, 2017

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

@marshall007
Copy link
Contributor

marshall007 commented Feb 23, 2018

@epoberezkin this seems especially bad in the case of $merge (see ajv-validator/ajv-merge-patch#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
{
  $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
Copy link
Member

@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
Copy link

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

@tobad357
Copy link

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
Copy link
Member

@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
Copy link

albanm commented Mar 15, 2023

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.

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

No branches or pull requests

7 participants