aboutsummaryrefslogtreecommitdiffstats
path: root/README.md
diff options
context:
space:
mode:
authorSimon Sparks2018-09-13 17:33:49 +0100
committerVincent Prouillet2018-09-13 18:33:49 +0200
commitdfdc289626c448522c43c13f8d72033fe0d1cae8 (patch)
treec2fcd006466c587040be8b88076c1477d908effc /README.md
parent5edb34ac261f7025ee0bb9c25ec1c216ded5aba2 (diff)
downloadvalidator-dfdc289626c448522c43c13f8d72033fe0d1cae8.tar.bz2
Nested Validation (#60)
* Nested Validation Added support for a plain validate attribute on a struct's field to imply that validate() should be called on it with results being merged. Validation errors are now keyed with a string that indicates the path to the invalid field within a complex data structure. The errors themselves also include the path to the invalid field, expressed as a vector of strings. Added support for option and vector fields where the wrapped values perform nested validation. Refactored vector wrapping for more reusable nested validation quoting. Vector index is now more conveniently represented as an individual item in the ValidationError's path attribute. A few ergonomic changes to support custom (i.e. non-derived) Validate implementations. A custom Validator implementation may either implement the validate() method as before or implement the new validate_path(ValidationPath) method which gives context of where the validation is taking place in a complex data structure. It is not necessary to implement both methods. Refactored ValidationErrors to adopt a structure reflecting that of the data being validated. Instead of holding a vector of ValidationError instances for each field, the ValidationErrors map may now include 3 different kinds of error values representing the field, nested struct and nested vector of struct scenarios. Note that this implies a breaking change to the ValidationErrors map and the "inner" method signature for accessing errors programmatically compared to previous versions. Added new accessor methods to the ValidationErrors type for retrieving either field-level errors for a validated struct or all errors for the struct and it's nested children. The existing `inner` method provides the field-level behaviour for backwards compatibility and has been marked as deprecated. Documented the new associated functions of the ValidationErrors implementation and removed unnecessary feature declaration in a test module. Refactored tests to use the new `field_errors` accessor method. Updated README.md to describe nested validation behaviour. Keats/validator#31
Diffstat (limited to 'README.md')
-rw-r--r--README.md81
1 files changed, 78 insertions, 3 deletions
diff --git a/README.md b/README.md
index 5a69c50..16ddd0e 100644
--- a/README.md
+++ b/README.md
@@ -53,7 +53,22 @@ match signup_data.validate() {
};
```
-An error has the following structure:
+The `validate()` method returns a `Result<(), ValidationErrors>`. In the case of an invalid result, the
+`ValidationErrors` instance includes a map of errors keyed against the struct's field names. Errors may be represented
+in three ways, as described by the `ValidationErrorsKind` enum:
+
+```rust
+#[derive(Debug, Serialize, Clone, PartialEq)]
+#[serde(untagged)]
+pub enum ValidationErrorsKind {
+ Struct(Box<ValidationErrors>),
+ List(BTreeMap<usize, Box<ValidationErrors>>),
+ Field(Vec<ValidationError>),
+}
+```
+
+In the simple example above, any errors would be of the `Field(Vec<ValidationError>)` type, where a single
+`ValidationError` has the following structure:
```rust
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
@@ -73,6 +88,57 @@ If you are adding a validation on a `Option<..>` field, it will only be ran if t
being `must_match` that doesn't currently work with `Option` due to me not finding a use case for it. If you have one,
please comment on https://github.com/Keats/validator/issues/7.
+The other two `ValidationErrorsKind` types represent errors discovered in nested (vectors of) structs, as described in
+this example:
+
+ ```rust
+#[macro_use]
+extern crate validator_derive;
+extern crate validator;
+#[macro_use]
+extern crate serde_derive;
+extern crate serde_json;
+
+#[derive(Debug, Validate, Deserialize)]
+struct SignupData {
+ #[validate]
+ contact_details: ContactDetails,
+ #[validate]
+ preferences: Vec<Preference>
+}
+
+#[derive(Debug, Validate, Deserialize)]
+struct ContactDetails {
+ #[validate(email)]
+ mail: String,
+ #[validate(phone)]
+ phone: String
+}
+
+#[derive(Debug, Validate, Deserialize)]
+struct Preference {
+ #[validate(length(min = "4"))]
+ name: String,
+ value: bool,
+}
+
+match signup_data.validate() {
+ Ok(_) => (),
+ Err(e) => return e;
+};
+ ```
+
+Here, the `ContactDetails` and `Preference` structs are nested within the parent `SignupData` struct. Because
+these child types also derive `Validate`, the fields where they appear can be tagged for inclusion in the parent
+struct's validation method.
+
+Any errors found in a single nested struct (the `contact_details` field in this example) would be returned as a
+`Struct(Box<ValidationErrors>)` type in the parent's `ValidationErrors` result.
+
+Any errors found in a vector of nested structs (the `preferences` field in this example) would be returned as a
+`List(BTreeMap<usize, Box<ValidationErrors>>)` type in the parent's `ValidationErrors` result, where the map is keyed on
+the index of invalid vector entries.
+
## Usage
You will need to import the `Validate` trait, and optionally use the `attr_literals` feature.
@@ -144,7 +210,7 @@ Examples:
```
### regex
-Tests whether the string matchs the regex given. `regex` takes
+Tests whether the string matches the regex given. `regex` takes
1 string argument: the path to a static Regex instance.
Examples:
@@ -154,7 +220,7 @@ Examples:
```
### credit\_card
-Test whetever the string is a valid credit card number.
+Test whether the string is a valid credit card number.
Examples:
@@ -181,6 +247,15 @@ Examples:
#[validate(custom = "::utils::validate_something")]
```
+### nested
+Performs validation on a field with a type that also implements the Validate trait (or a vector of such types).
+
+Examples:
+
+```rust
+#[validate]
+```
+
## Struct level validation
Often, some error validation can only be applied when looking at the full struct, here's how it works here: