23andMe / Yamale

A schema and validator for YAML.
MIT License
672 stars 88 forks source link

Validating a list of "dictionaries" #147

Closed SuperSajuuk closed 3 years ago

SuperSajuuk commented 3 years ago

I have a schema that works out very well, but there's one issue: one part of my YAML files can include a key where the values are a list of dictionary values (ie, each element is a key/value pair. How would I go about validating this?

The most I know is that I need a list (since the root key is going to be a list), but the values of each list are dictionaries which doesn't seem to have a validator available atm?

EDIT: I think the correct method is list(map(str(), key=str()), required=False, none=True), is this correct?

mechie commented 3 years ago

An example/snippet of the YAML you are trying to validate would be very helpful, descriptions are much harder to nail down.

The schema you posted would validate data like this...

- k1: v1
  k2: v2
  k3: v3
- k1: v1
  k2: v2
- k3: v3
- k4: v4

While a schema like map(map(str(), key=str()), key=str(), required=False, none=True) would validate data like...

entry1:
  k1: v1
  k2: v2
  k3: v3
entry2:
  k1: v1
  k2: v2
entry3:
  k3: v3
entry4:
  k4: v4

And a schema like list(map(map(str(), key=str()), key=str()), required=False, none=True) would validate data like...

- entry1:
    k1: v1
    k2: v2
    k3: v3
- entry2:
    k1: v1
    k2: v2
- entry3:
    k3: v3
- entry4:
    k4: v4

Unrelated, but you'll end up with much more readable and maintainable schemas if you use include() when nesting complicated validators. For example, list(map(str(), key=str()), required=False, none=True) can be written as...

list(include('str_str_dict'), required=False, none=True)
---
str_str_dict: map(str(), key=str())

Hope this all helps!

SuperSajuuk commented 3 years ago

@mechie Thanks! Since the schema is very long, I'll include only the relevant bits: Base Schema is this:

custom commands: include('customCommands', required=False)

The included section:

customCommands:
  enabled: bool(required=False)
  commands: list(map(str(min=1, max=16), key=str(min=1)), required=False, none=True)

In actual use, someone would do this:

custom commands:
  enabled: true
  commands:
  - "!invite": invite
  - "?invite": invite

The list can only be formatted like that, as otherwise it won't function in the intended environment (a discord bot).

mildebrandt commented 3 years ago

Hi, thanks for using Yamale! What you have will work just fine. If you need to constrain the keys of the map further, you can use the regex validator instead of the str validator.

And thanks @mechie for jumping in to help answer questions.

SuperSajuuk commented 3 years ago

Thank you @mildebrandt for confirming that my schema is accurate! Will close this now :)

ilia-wolke7 commented 2 years ago

Hi @mechie, you are write

[And a schema like list(map(map(str(), key=str()), key=str()), required=False, none=True) would validate data like...

Unfortunately it doesn't work for me. Please help me to write a schema for following example:

graph:
  list:
    - some_string_link_name:
      start_node: 0
      end_node: 3
    - some_other_string_link_name:
      start_node: 1
      end_node: 3
    - some_other_string2_link_name:
      start_node: 2
      end_node: 3

Thank you in advance

mildebrandt commented 2 years ago

@ilia-wolke7 Let's keep the conversation for your issue in https://github.com/23andMe/Yamale/issues/184. Thanks!