Skip to content
Permalink
Browse files

Implement ability to pass custom validators to JsonSchemaValidator (#…

  • Loading branch information...
PonasJustas authored and RicoSuter committed Nov 8, 2019
1 parent 1a2ce00 commit e880e6e1bb724862f8fcd78a0ab03ac9fe3e0240
@@ -0,0 +1,58 @@
using Newtonsoft.Json.Linq;
using NJsonSchema.Validation;
using NJsonSchema.Validation.FormatValidators;
using System;
using System.Globalization;
using Xunit;

namespace NJsonSchema.Tests.Validation
{
public class CustomValidationTests
{
[Fact]
public void When_format_date_time_correct_with_custom_validator_passed_then_no_errors()
{
//// Arrange
var schema = new JsonSchema
{
Type = JsonObjectType.String,
Format = JsonFormatStrings.DateTime
};

var token = new JValue("2014-12-01 11:00:01:55");

//// Act
var errors = schema.Validate(token, new CustomDateTimeFormatValidator());

//// Assert
Assert.Empty(errors);
}

private class CustomDateTimeFormatValidator : IFormatValidator
{
private readonly string[] _acceptableFormats = {
"yyyy'-'MM'-'dd HH':'mm':'ss':'ff"
};

/// <summary>
/// Gets the format attributes value.
/// </summary>
public string Format { get; } = JsonFormatStrings.DateTime;

/// <summary>
/// Gets the validation error kind.
/// </summary>
public ValidationErrorKind ValidationErrorKind { get; } = ValidationErrorKind.DateTimeExpected;

/// <summary>Validates if a string is valid DateTime.</summary>
/// <param name="value">String value.</param>
/// <param name="tokenType">Type of token holding the value.</param>
/// <returns></returns>
public bool IsValid(string value, JTokenType tokenType)
{
return tokenType == JTokenType.Date
|| DateTimeOffset.TryParseExact(value, _acceptableFormats, CultureInfo.InvariantCulture, DateTimeStyles.None, out _);
}
}
}
}
@@ -20,6 +20,7 @@
using NJsonSchema.Generation;
using NJsonSchema.Infrastructure;
using NJsonSchema.Validation;
using NJsonSchema.Validation.FormatValidators;

namespace NJsonSchema
{
@@ -839,20 +840,22 @@ public bool InheritsSchema(JsonSchema parentSchema)

/// <summary>Validates the given JSON data against this schema.</summary>
/// <param name="jsonData">The JSON data to validate. </param>
/// <param name="customValidators">Custom validators to validate the JSON.</param>
/// <exception cref="JsonReaderException">Could not deserialize the JSON data.</exception>
/// <returns>The collection of validation errors. </returns>
public ICollection<ValidationError> Validate(string jsonData)
public ICollection<ValidationError> Validate(string jsonData, params IFormatValidator[] customValidators)
{
var validator = new JsonSchemaValidator();
var validator = new JsonSchemaValidator(customValidators);
return validator.Validate(jsonData, ActualSchema);
}

/// <summary>Validates the given JSON token against this schema.</summary>
/// <param name="token">The token to validate. </param>
/// <param name="customValidators">Custom validators to validate the token.</param>
/// <returns>The collection of validation errors. </returns>
public ICollection<ValidationError> Validate(JToken token)
public ICollection<ValidationError> Validate(JToken token, params IFormatValidator[] customValidators)
{
var validator = new JsonSchemaValidator();
var validator = new JsonSchemaValidator(customValidators);
return validator.Validate(token, ActualSchema);
}

@@ -36,14 +36,14 @@ public class JsonSchemaValidator
new Base64FormatValidator()
};

private readonly IDictionary<string, IFormatValidator> _formatValidatorsMap;
private readonly IDictionary<string, IFormatValidator[]> _formatValidatorsMap;

/// <summary>
/// Initializes JsonSchemaValidator
/// </summary>
public JsonSchemaValidator()
public JsonSchemaValidator(params IFormatValidator[] customValidators)
{
_formatValidatorsMap = _formatValidators.ToDictionary(v => v.Format, v => v);
_formatValidatorsMap = _formatValidators.Union(customValidators).GroupBy(x => x.Format).ToDictionary(v => v.Key, v => v.ToArray());
}

/// <summary>Validates the given JSON data.</summary>
@@ -234,17 +234,11 @@ private void ValidateString(JToken token, JsonSchema schema, JsonObjectType type
}

if (!string.IsNullOrEmpty(schema.Format)
&& _formatValidatorsMap.TryGetValue(schema.Format, out var formatValidator)
&& !formatValidator.IsValid(value, token.Type))
&& _formatValidatorsMap.TryGetValue(schema.Format, out var formatValidators)
&& !formatValidators.Any(x => x.IsValid(value, token.Type)))
{
var error = new ValidationError(
formatValidator.ValidationErrorKind,
propertyName,
propertyPath,
token,
schema);

errors.Add(error);
errors.AddRange(formatValidators.Select(x => x.ValidationErrorKind).Distinct()
.Select(validationErrorKind => new ValidationError(validationErrorKind, propertyName, propertyPath, token, schema)));
}
}
}

0 comments on commit e880e6e

Please sign in to comment.
You can’t perform that action at this time.