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

Schema validation with dynamic keys #2516

Closed
f-delahaye opened this issue Feb 22, 2024 · 3 comments
Closed

Schema validation with dynamic keys #2516

f-delahaye opened this issue Feb 22, 2024 · 3 comments

Comments

@f-delahaye
Copy link
Contributor

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?

@ptrthomas
Copy link
Member

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

@f-delahaye
Copy link
Contributor Author

f-delahaye commented Feb 29, 2024

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.

@f-delahaye
Copy link
Contributor Author

(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!)

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

No branches or pull requests

2 participants