karatelabs / karate

Test Automation Made Simple

Home Page:https://karatelabs.github.io/karate

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Schema validation with dynamic keys

f-delahaye opened this issue · comments

There are a few posts in StackOverflow asking how to use Karate's schema validation against data with dynamic keys.

This one is a pretty good example:

    "data": {
        "PHX": {
            "name": "Phoenix (All)",
            "city_code": "PHX",
            (...)
            "airports": {
                "SCF": {
                    "name": "Scottsdale Municipalcipal",
               (...)
                },
                "PHX": {
                    "name": "Sky Harbor International",
                    (...)
                }

Peter's suggestion works:

* def data = []
* karate.forEach(response.data.PHX.airports, (k, v) => { v.code = k; data.push(v) })

but the mor.e properties there are in the json, especially nested ones as in the example above, the more complicated it is to implement. Isn't Karate all about simplicity ;)

What the user was trying to achieve:
'data: {#string: {name: #string, city_code: #string, airports: {#string: {name: #string}}}'
is a step in the right direction, IMHO.

Looking at the code, it does not seem too complicated to implement.
However, Karate currently does not support fuzzy logic on keys, only on values.
Any reason for that? Any objections to add it?

Also, I think airports: {#string: {name: #string}} is a bit misleading. It seems to imply a key of type string having an object with a property name of type string, when in fact, we want to match a set of keys, each having an object with a property name.

Therefore, we could introduce a new #dict marker (as in Python's dictionary) that would be used as follows:
data: {#dict: {name: #string, city_code: #string, airports: {#dict: {name: #string}}}

@ptrthomas What do you think?

not sure if this is simple tbh. personally I consider the need to validate keys rare and due to badly designed APIs. also am more worried about issues like this: #2515 - because that is core to karate

the last line is honestly a bit hard to read and understand. so I'm concerned about that. you are welcome to try a PR

Thanks @ptrthomas

Agreed about the last line being a bit hard to read.
For consistency with the other fuzzy markers, maybe declaring #dict as a property, not a key, would make more sense.
Something like:

{ data: #dict({
    name: #string,
    airports: #dict({
      name: #string
   }
}

Not sure it would be more understandable, though. And definitely very complicated to implement.

The other interesting thing in your comment is issue #2515. There's a risk, albeit small IMO, that this new marker would introduce a similar regression. Also, how would it integrate with contains [only [deep]]? Something to thing about ...

Anyway, I'm hoping to raise a PR for feedback in the coming days, with the initial suggestion.

(on hold while looking at #2515 and learning more about shortcuts and whether they could help here. It seems that every month i learn a new amazing feature in Karate!)