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

Add support for Dictionary #26

Open
kislovs opened this issue Jul 28, 2022 · 7 comments
Open

Add support for Dictionary #26

kislovs opened this issue Jul 28, 2022 · 7 comments
Assignees
Labels
enhancement New feature or request
Milestone

Comments

@kislovs
Copy link

kislovs commented Jul 28, 2022

Feature description

  • To have ability validating dictionary as key-value map, not as collection of key-value pair.

Feature in action

Specification<string> keySpecification = s => s
    .Rule(subj => subj != "foo").WithMessage("Key must not be 'foo'!");

Specification<double> valueSpecification = s => s
    .Rule(subj => subj > 0).WithMessage("Value must be positive!");

Specification<IReadOnlyDictionary<string, double>> specification = s => s
    .AsDictionary(keySpecification, valueSpecification);

var validator = Validator.Factory.Create(specification);

var dictionary = new Dictionary<string, double>{
    ["foo"] = 0,
    ["bar"] = 0,
    ["baz"] = 100
};

validator.Validate(dictionary).ToString();
// #foo: Key must not be 'foo'!
// #foo: Value must be positive! | only if skip is not enabled
// #bar: Value must be positive!

Feature details

  • Validation of Dictionary require validating each TKey, each TValue separately.
  • Both of validation should have access to the full Dictionary to check possible relations (?).
  • Instead of #0 syntax in error messages, #key should be used.

Discussion

  • Consider to add option to skip TValue validation if TKey failed.
  • What to do with complex TKey in #key printing:
    • Just use .ToString()
    • Add WithKey method
@bartoszlenar
Copy link
Owner

OK, that's actually interesting. Thank you @kislovs for pointing this out, I think I will work on that soon.

Few caveats, though:

  • I don't imagine validating keys should be in the scope. I'd rather have AsDictionary that validates only the values (error outputs saved under the path that uses the related dictionary key)
  • Probably there should be some constrains for dictionary key type (e.g., numbers and string). Raw ToString() isn't reliable enough, but will think about it.
  • Keys landing in the path are a problem for the current path system, so PathHelper needs to be updated as well.

Not a small task, so I won't be pushing that one in the upcoming release, but maybe the next one.

@kislovs
Copy link
Author

kislovs commented Jul 29, 2022

Just to clarify, if it'll have some constraints, it also must have some .WithKey helper or it'll be impossible to use when you're fighting with Primitive obsession (e.g. using AccountId(string Value) instead of raw string)

@bartoszlenar
Copy link
Owner

You're right, however I think I'd proceed with placing required parameters together, so if it does use string as a key, it would be

.AsDictionary(valueSpec)

if not string, something like

.AsDictionary(keySelector, valueSpec), where keySelector is a Func<TKey, string> transforming TKey to the string key that lands in the error output's path.

In any way, I'm scheduling this one after #3 and #24 .

As it's messing up with some internal parts, I'd prefer to code it myself.

@bartoszlenar
Copy link
Owner

@kislovs #3 is completed as for this moment and I will be slowly drafting how AsDictionary could be efficiently implemented.

I think this could introduce some breaking changes (so v3.0.0), mainly because of the paths under which errors are saved. Externally, IValidationResult.MessageMap and WithPath command would be affected for sure. Storing path as a collection of nested segments instead of a simple string will affect the memory efficiency, so I need to handle it somehow.

@bartoszlenar
Copy link
Owner

@kislovs
Most probably, the solution would look like I described above in #26 (comment) .

To avoid introducing breaking changes, messing up with the performance and to significantly reduce the development time, the keys will be always "normalized" to the version accepted by the WithPath command.

Most probably it will be part of 2.5, published later this year.

@bartoszlenar bartoszlenar added this to the v2.5 milestone Dec 6, 2022
@bartoszlenar bartoszlenar modified the milestones: v2.5, v3.1 Dec 14, 2022
@adambajguz
Copy link

Hello @bartoszlenar,
any updates on this?

@bartoszlenar
Copy link
Owner

Hello @bartoszlenar, any updates on this?

I scheduled it for v3.1, so expect it somewhere in April.

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

No branches or pull requests

3 participants