ajv-keywords icon indicating copy to clipboard operation
ajv-keywords copied to clipboard

deepProperties support for relative and absolute pointers

Open kobyl opened this issue 8 years ago • 3 comments

Hello,

From the readme for deepProperties: This keyword allows to validate deep properties (identified by JSON pointers).

I have a need to validate 'cousin' properties inside an array. I've tried this:

let schema = {
    deepProperties : { "/parent/child1/grandchild1" : {
        deepProperties : { "2/child2/grandchild2" : { const : true }}
    }}
};

let data = {
    parent : {
        child1 : {
            grandchild1: true
        },
        child2 : {
            grandchild2: false
        }
    }
};

And got: keyword schema is invalid: data should match format "json-pointer", data property name '2/child2/grandchild2' is invalid.

Tracing a bit - it looks like the validation code from ajv/lib doesn't support relative pointers. I can build another custom keyword to wrap deepProperties I think, but wanted to report this either for fixing or for clarifying.

Thanks!

Koby

kobyl avatar Sep 12 '17 16:09 kobyl

I don't understand why you need to validate one deep property from another.

It's possible to allow root-based absolute and relative JSON pointers, but that would mean full rewrite of this keywords and changes in deepRequired - should be a major version change.

epoberezkin avatar Sep 13 '17 15:09 epoberezkin

I thought about this some more, and I think you're right - I may not need it. I'm doing government forms and have ridiculously complex rules, and am looking to write a generic form and rule generator.

Suppose I have data that looks like this:

{
    vehicles: [
        {
            id: 1,
            make: 'honda',
            model: 'accord',
            //... year, vin, etc
            driver: {
                firstname: 'john',
                lastname: 'doe',
                //...
            },
            passengers: [
                {
                    firstname: 'jane',
                    lastname: 'doe',
                    //...
                },
                //... More passengers
            ],
            damage: {
                //...
            }
        },
        {
            id: 2,
            //... year, vin, etc
            driver: {
                firstname: 'none',
                //...
            },            passengers: [],
            damage: {
                //...
            }
        },
    ],
    incident: {
        date: 'thedate',
        time: '...',
        parked: true,
    }
}

The rule might be "if incident.parked is true, then at least one vehicle's driver must have firstname='none' and also have at least one element in its damage section"

For the last part(about the driver firstname and the damage section - I was thinking of using deep properties like so:

{
  properties: {
      vehicles: { allOf : {
        deepProperties: {"/driver/firstname" : {const: 'unknown'}}, },
        deepProperties: {"1/damage" : // Needs at least one element... 
        }
      }...
}

kobyl avatar Sep 13 '17 16:09 kobyl

The last snippet is equivalent to:

{
  properties: {
    vehicles: {
      deepProperties: {
        "/driver/firstname" : {const: 'unknown'},
        "1/damage" : // I assume it should not be relative in this case as well 
      }
    }
  }
}

epoberezkin avatar Sep 13 '17 17:09 epoberezkin