/// <summary> /// Provides the validation logic for this keyword. /// </summary> /// <param name="context">The context object.</param> /// <returns>Results object containing a final result and any errors that may have been found.</returns> public SchemaValidationResults Validate(SchemaValidationContext context) { var results = new SchemaValidationResults(Name, context); var newContext = new SchemaValidationContext(context) { BaseRelativeLocation = context.BaseRelativeLocation?.CloneAndAppend(Name), RelativeLocation = context.RelativeLocation.CloneAndAppend(Name), }; var nestedResults = Value.Validate(newContext); results.IsValid = !nestedResults.IsValid; if (!results.IsValid) { Log.Schema("Subschema succeeded; inverting result"); results.ErrorMessage = ErrorTemplate; } if (JsonSchemaOptions.OutputFormat != SchemaValidationOutputFormat.Flag && JsonSchemaOptions.ShouldReportChildErrors(this, context)) { results.NestedResults = new List <SchemaValidationResults> { nestedResults } } ; return(results); }
/// <summary> /// Downloads and registers a schema at the specified URI. /// </summary> public static JsonSchema Get(string uri) { JsonSchema schema; lock (_schemaLookup) { uri = uri.TrimEnd('#'); if (!_schemaLookup.TryGetValue(uri, out schema)) { var schemaJson = JsonSchemaOptions.Download(uri); var schemaValue = JsonValue.Parse(schemaJson); schema = new JsonSchema { DocumentPath = new Uri(uri, UriKind.RelativeOrAbsolute) }; schema.FromJson(schemaValue, _serializer); var structureErrors = schema.ValidateSchema(); if (!structureErrors.IsValid) { throw new SchemaLoadException("The given path does not contain a valid schema.", structureErrors); } _schemaLookup[uri] = schema; } } return(schema); }
/// <summary> /// Provides the validation logic for this keyword. /// </summary> /// <param name="context">The context object.</param> /// <returns>Results object containing a final result and any errors that may have been found.</returns> public SchemaValidationResults Validate(SchemaValidationContext context) { var results = new SchemaValidationResults(Name, context); if (context.Instance.Type != JsonValueType.Object) { Log.Schema("Instance not an object; not applicable"); return(results); } var baseRelativeLocation = context.BaseRelativeLocation?.CloneAndAppend(Name); var relativeLocation = context.RelativeLocation.CloneAndAppend(Name); var valid = true; var reportChildErrors = JsonSchemaOptions.ShouldReportChildErrors(this, context); var nestedResults = new List <SchemaValidationResults>(); var invalidPropertyNames = new JsonArray(); foreach (var propertyName in context.Instance.Object.Keys) { var newContext = new SchemaValidationContext(context) { Instance = propertyName, BaseRelativeLocation = baseRelativeLocation, RelativeLocation = relativeLocation, InstanceLocation = context.InstanceLocation.CloneAndAppend(propertyName), }; var localResults = Value.Validate(newContext); valid &= localResults.IsValid; if (!valid) { invalidPropertyNames.Add(propertyName); } if (JsonSchemaOptions.OutputFormat == SchemaValidationOutputFormat.Flag) { if (!valid) { Log.Schema("Subschema failed; halting validation early"); break; } } else if (reportChildErrors) { nestedResults.Add(localResults); } } results.IsValid = valid; results.NestedResults = nestedResults; if (!results.IsValid) { Log.Schema($"Property names {invalidPropertyNames.ToJson()} failed"); results.AdditionalInfo["properties"] = invalidPropertyNames; results.ErrorMessage = ErrorTemplate.ResolveTokens(results.AdditionalInfo); } return(results); }
/// <summary> /// Provides the validation logic for this keyword. /// </summary> /// <param name="context">The context object.</param> /// <returns>Results object containing a final result and any errors that may have been found.</returns> public SchemaValidationResults Validate(SchemaValidationContext context) { var baseRelativeLocation = context.BaseRelativeLocation?.CloneAndAppend(Name); var relativeLocation = context.RelativeLocation.CloneAndAppend(Name); var valid = true; var reportChildErrors = JsonSchemaOptions.ShouldReportChildErrors(this, context); var nestedResults = new List <SchemaValidationResults>(); var failedCount = 0; foreach (var d in this) { var newContext = new SchemaValidationContext(context) { BaseRelativeLocation = baseRelativeLocation, RelativeLocation = relativeLocation, Misc = { ["dependencyParent"] = Name } }; var localResults = d.Validate(newContext); valid &= localResults.IsValid; if (!valid) { failedCount++; } if (JsonSchemaOptions.OutputFormat == SchemaValidationOutputFormat.Flag) { if (!valid) { Log.Schema("Dependency failed; halting validation early"); break; } } else if (reportChildErrors) { nestedResults.Add(localResults); } } var results = new SchemaValidationResults(Name, context) { IsValid = valid }; if (JsonSchemaOptions.OutputFormat == SchemaValidationOutputFormat.Flag) { results.NestedResults = nestedResults; } else if (!results.IsValid) { results.AdditionalInfo["failed"] = failedCount; results.AdditionalInfo["total"] = Count; results.ErrorMessage = ErrorTemplate.ResolveTokens(results.AdditionalInfo); } return(results); }
/// <summary> /// Provides the validation logic for this keyword. /// </summary> /// <param name="context">The context object.</param> /// <returns>Results object containing a final result and any errors that may have been found.</returns> public SchemaValidationResults Validate(SchemaValidationContext context) { var reportChildErrors = JsonSchemaOptions.ShouldReportChildErrors(this, context); var i = 0; var nestedResults = new List <SchemaValidationResults>(); var validCount = 0; var contextCopy = new SchemaValidationContext(context); foreach (var s in this) { var newContext = new SchemaValidationContext(context) { BaseRelativeLocation = context.BaseRelativeLocation?.CloneAndAppend(Name, i.ToString()), RelativeLocation = context.RelativeLocation.CloneAndAppend(Name, i.ToString()), }; var localResults = s.Validate(newContext); if (localResults.IsValid) { validCount++; } Log.Schema($"`{Name}` {validCount} items valid so far"); contextCopy.UpdateEvaluatedPropertiesAndItemsFromSubschemaValidation(newContext); if (JsonSchemaOptions.OutputFormat == SchemaValidationOutputFormat.Flag) { if (validCount > 1) { Log.Schema("More than one subschema succeeded; halting validation early"); break; } } else if (reportChildErrors) { nestedResults.Add(localResults); } } var results = new SchemaValidationResults(Name, context) { IsValid = validCount == 1, NestedResults = nestedResults }; if (!results.IsValid) { Log.Schema($"{validCount} subschemas passed validation; expected only one"); results.AdditionalInfo["passed"] = validCount; results.ErrorMessage = ErrorTemplate.ResolveTokens(results.AdditionalInfo); } else { context.UpdateEvaluatedPropertiesAndItemsFromSubschemaValidation(contextCopy); } return(results); }
/// <summary> /// Provides the validation logic for this keyword. /// </summary> /// <param name="context">The context object.</param> /// <returns>Results object containing a final result and any errors that may have been found.</returns> public SchemaValidationResults Validate(SchemaValidationContext context) { var valid = true; var reportChildErrors = JsonSchemaOptions.ShouldReportChildErrors(this, context); var i = 0; var nestedResults = new List <SchemaValidationResults>(); var failedCount = 0; foreach (var s in this) { var newContext = new SchemaValidationContext(context) { BaseRelativeLocation = context.BaseRelativeLocation?.CloneAndAppend(Name, i.ToString()), RelativeLocation = context.RelativeLocation.CloneAndAppend(Name, i.ToString()), }; var localResults = s.Validate(newContext); valid &= localResults.IsValid; Log.Schema($"`{Name}` {(valid ? "valid" : "invalid")} so far"); if (!valid) { failedCount++; } context.UpdateEvaluatedPropertiesAndItemsFromSubschemaValidation(newContext); if (JsonSchemaOptions.OutputFormat == SchemaValidationOutputFormat.Flag) { if (!valid) { Log.Schema("Subschema failed; halting validation early"); break; } } else if (reportChildErrors) { nestedResults.Add(localResults); } i++; } var results = new SchemaValidationResults(Name, context) { NestedResults = nestedResults, IsValid = valid }; if (!results.IsValid) { results.AdditionalInfo["failed"] = failedCount; results.AdditionalInfo["total"] = Count; results.ErrorMessage = ErrorTemplate.ResolveTokens(results.AdditionalInfo); } return(results); }
/// <summary> /// Downloads and registers a schema at the specified URI. /// </summary> public static IJsonSchema Get(string uri) { IJsonSchema schema; lock (_schemaLookup) { uri = uri.TrimEnd('#'); if (!_schemaLookup.TryGetValue(uri, out schema)) { var schemaJson = JsonSchemaOptions.Download(uri); var schemaValue = JsonValue.Parse(schemaJson); schema = JsonSchemaFactory.FromJson(schemaValue, new Uri(uri)); var metaSchemas = new IJsonSchema[] { JsonSchema07.MetaSchema, JsonSchema06.MetaSchema, JsonSchema04.MetaSchema }; SchemaValidationResults validation = null; if (schema.Schema != null) { var bySchema = metaSchemas.FirstOrDefault(s => s.Id == schema.Schema); if (bySchema != null) { validation = bySchema.Validate(schemaValue); } } else { foreach (var metaSchema in metaSchemas) { validation = metaSchema.Validate(schemaValue); if (validation.Valid) { break; } } } if (validation != null && !validation.Valid) { var errors = string.Join(Environment.NewLine, validation.Errors.Select(e => e.Message)); throw new ArgumentException($"The given path does not contain a valid schema. Errors: \n{errors}"); } _schemaLookup[uri] = schema; } } return(schema); }
/// <summary> /// Creates a new instance of the <see cref="JsonSchemaOptions"/> class. /// </summary> public JsonSchemaOptions(JsonSchemaOptions source) { _errorCollectionConditions = source._errorCollectionConditions.ToList(); ValidateFormatKeyword = source.ValidateFormatKeyword; AllowUnknownFormats = source.AllowUnknownFormats; OutputFormat = source.OutputFormat; RefResolution = source.RefResolution; DefaultBaseUri = source.DefaultBaseUri; LogMetaSchemaValidation = source.LogMetaSchemaValidation; DefaultProcessingVersion = source.DefaultProcessingVersion; ConfigureForTestOutput = source.ConfigureForTestOutput; }
#pragma warning disable CS8618 // Non-nullable field is uninitialized. Consider declaring as nullable. internal SchemaValidationContext(JsonSchema root, JsonValue instance, JsonPointer?baseRelativeLocation, JsonPointer relativeLocation, JsonPointer instanceLocation, JsonSchemaOptions options) #pragma warning restore CS8618 // Non-nullable field is uninitialized. Consider declaring as nullable. { Root = root; Instance = instance; BaseRelativeLocation = baseRelativeLocation; RelativeLocation = relativeLocation; InstanceLocation = instanceLocation; LocalRegistry = new JsonSchemaRegistry(); Options = options; }
/// <summary> /// Provides the validation logic for this keyword. /// </summary> /// <param name="context">The context object.</param> /// <returns>Results object containing a final result and any errors that may have been found.</returns> public SchemaValidationResults Validate(SchemaValidationContext context) { if (!context.Misc.TryGetValue("ifKeywordValid", out var ifKeywordValidStore)) { Log.Schema("`if` keyword not present; not applicable"); return(new SchemaValidationResults(Name, context)); } var ifKeywordValid = (bool)ifKeywordValidStore; if (!ifKeywordValid) { Log.Schema("`if` subschema failed; not applicable"); return(new SchemaValidationResults(Name, context)); } var results = new SchemaValidationResults(Name, context); var newContext = new SchemaValidationContext(context) { BaseRelativeLocation = context.BaseRelativeLocation?.CloneAndAppend(Name), RelativeLocation = context.RelativeLocation.CloneAndAppend(Name), }; var thenResults = Value.Validate(newContext); if (!thenResults.IsValid) { Log.Schema("`if` subschema succeeded, but `then` subschema failed"); results.IsValid = false; results.Keyword = Name; results.ErrorMessage = ErrorTemplate; if (JsonSchemaOptions.ShouldReportChildErrors(this, context)) { results.NestedResults.Add(thenResults); } } return(results); }
/// <summary> /// Provides the validation logic for this keyword. /// </summary> /// <param name="context">The context object.</param> /// <returns>Results object containing a final result and any errors that may have been found.</returns> public SchemaValidationResults Validate(SchemaValidationContext context) { if (context.Instance.Type != JsonValueType.Array) { Log.Schema("Instance not an array; not applicable"); return(new SchemaValidationResults(Name, context)); } var nestedResults = new List <SchemaValidationResults>(); var array = context.Instance.Array; var results = new SchemaValidationResults(Name, context); var valid = true; var reportChildErrors = JsonSchemaOptions.ShouldReportChildErrors(this, context); var startIndex = context.LastEvaluatedIndex + 1; Log.Schema(startIndex == 0 ? "No indices have been evaluated; process all" : $"Indices up to {context.LastEvaluatedIndex} have been evaluated; skipping these"); if (startIndex < array.Count) { if (Value == JsonSchema.False) { Log.Schema("Subschema is `false`; all instances invalid"); results.IsValid = false; results.Keyword = Name; results.ErrorMessage = ErrorTemplate; return(results); } var eligibleItems = array.Skip(startIndex); var index = startIndex; foreach (var item in eligibleItems) { var baseRelativeLocation = context.BaseRelativeLocation?.CloneAndAppend(Name); var relativeLocation = context.RelativeLocation.CloneAndAppend(Name); var newContext = new SchemaValidationContext(context) { Instance = item, BaseRelativeLocation = baseRelativeLocation, RelativeLocation = relativeLocation, InstanceLocation = context.InstanceLocation.CloneAndAppend(index.ToString()), }; var localResults = Value.Validate(newContext); valid &= localResults.IsValid; if (valid) { context.UpdateEvaluatedPropertiesAndItemsFromSubschemaValidation(newContext); } index++; if (JsonSchemaOptions.OutputFormat == SchemaValidationOutputFormat.Flag) { if (!valid) { Log.Schema("Subschema failed; halting validation early"); break; } } else if (reportChildErrors) { nestedResults.Add(localResults); } } } else { Log.Schema("All items have been validated"); } results.NestedResults = nestedResults; results.IsValid = valid; results.Keyword = Name; if (!valid) { results.ErrorMessage = ErrorTemplate; } return(results); }
/// <summary> /// Provides the validation logic for this keyword. /// </summary> /// <param name="context">The context object.</param> /// <returns>Results object containing a final result and any errors that may have been found.</returns> public SchemaValidationResults Validate(SchemaValidationContext context) { if (context.Instance.Type != JsonValueType.Object) { Log.Schema("Instance not an object; not applicable"); return(new SchemaValidationResults(Name, context)); } var obj = context.Instance.Object; var results = new SchemaValidationResults(Name, context); var toEvaluate = obj.Where(kvp => !context.EvaluatedPropertyNames.Contains(kvp.Key)) !.ToJson(); if (toEvaluate.Count == 0) { Log.Schema("All properties have been evaluated"); return(results); } Log.Schema(context.EvaluatedPropertyNames.Count == 0 ? "No properties have been evaluated; process all" : $"Properties {context.EvaluatedPropertyNames.ToJson()} have been evaluated; skipping these"); if (Value == JsonSchema.False && toEvaluate.Any()) { Log.Schema("Subschema is `false`; all instances invalid"); results.IsValid = false; results.Keyword = Name; results.ErrorMessage = ErrorTemplate; return(results); } var valid = true; var reportChildErrors = JsonSchemaOptions.ShouldReportChildErrors(this, context); var nestedResults = new List <SchemaValidationResults>(); foreach (var kvp in toEvaluate) { var newContext = new SchemaValidationContext(context) { Instance = kvp.Value, BaseRelativeLocation = context.BaseRelativeLocation?.CloneAndAppend(Name), RelativeLocation = context.RelativeLocation.CloneAndAppend(Name), InstanceLocation = context.InstanceLocation.CloneAndAppend(kvp.Key), }; var localResults = Value.Validate(newContext); valid &= localResults.IsValid; if (JsonSchemaOptions.OutputFormat == SchemaValidationOutputFormat.Flag) { if (!valid) { Log.Schema("Subschema failed; halting validation early"); break; } } else if (reportChildErrors) { nestedResults.Add(localResults); } } results.NestedResults = nestedResults; if (nestedResults.Any(r => !r.IsValid)) { results.IsValid = false; results.Keyword = Name; results.ErrorMessage = ErrorTemplate; } return(results); }
/// <summary> /// Provides the validation logic for this keyword. /// </summary> /// <param name="context">The context object.</param> /// <returns>Results object containing a final result and any errors that may have been found.</returns> public SchemaValidationResults Validate(SchemaValidationContext context) { if (context.Instance.Type != JsonValueType.Array) { Log.Schema("Instance not an array; not applicable"); return(new SchemaValidationResults(Name, context)); } var baseRelativeLocation = context.BaseRelativeLocation?.CloneAndAppend(Name); var relativeLocation = context.RelativeLocation.CloneAndAppend(Name); var valid = false; var reportChildErrors = JsonSchemaOptions.ShouldReportChildErrors(this, context); var i = 0; var nestedResults = new List <SchemaValidationResults>(); var matchedIndices = new JsonArray(); var hasMinMaxConstraints = context.Local.Get <MinContainsKeyword>() != null || context.Local.Get <MaxContainsKeyword>() != null; foreach (var jv in context.Instance.Array) { var newContext = new SchemaValidationContext(context) { Instance = jv, BaseRelativeLocation = baseRelativeLocation, RelativeLocation = relativeLocation, InstanceLocation = context.InstanceLocation.CloneAndAppend(i.ToString()), }; var localResults = Value.Validate(newContext); valid |= localResults.IsValid; if (localResults.IsValid) { matchedIndices.Add(i); } if (JsonSchemaOptions.OutputFormat == SchemaValidationOutputFormat.Flag) { if (valid && !hasMinMaxConstraints) { Log.Schema("Match found and no min/max constraints; halting validation early"); break; } } else if (reportChildErrors) { nestedResults.Add(localResults); } i++; } Log.Schema($"Found {matchedIndices.Count} instances that match; saving for later"); context.Misc["containsCount"] = matchedIndices.Count; var results = new SchemaValidationResults { NestedResults = nestedResults, IsValid = valid, Keyword = Name, AdditionalInfo = { ["matchedIndices"] = matchedIndices } }; if (!valid) { results.ErrorMessage = ErrorTemplate; } return(results); }
/// <summary> /// Provides the validation logic for this keyword. /// </summary> /// <param name="context">The context object.</param> /// <returns>Results object containing a final result and any errors that may have been found.</returns> public SchemaValidationResults Validate(SchemaValidationContext context) { var results = new SchemaValidationResults(Name, context); if (context.Instance.Type != JsonValueType.Object) { Log.Schema("Instance not an object; not applicable"); return(results); } var nestedResults = new List <SchemaValidationResults>(); var obj = context.Instance.Object; var reportChildErrors = JsonSchemaOptions.ShouldReportChildErrors(this, context); var valid = true; foreach (var patternProperty in this) { var pattern = new Regex(patternProperty.Key); var localSchema = patternProperty.Value; var matches = obj.Keys.Where(k => pattern.IsMatch(k)); if (matches.Any()) { Log.Schema($"Properties {matches.ToJson()} are matches for regular expression \"{pattern}\""); var baseRelativeLocation = context.BaseRelativeLocation?.CloneAndAppend(Name, patternProperty.Key); var relativeLocation = context.RelativeLocation.CloneAndAppend(Name, patternProperty.Key); foreach (var match in matches) { context.EvaluatedPropertyNames.Add(match); context.LocallyEvaluatedPropertyNames.Add(match); var newContext = new SchemaValidationContext(context) { Instance = obj[match], BaseRelativeLocation = baseRelativeLocation, RelativeLocation = relativeLocation, InstanceLocation = context.InstanceLocation.CloneAndAppend(match), }; var localResults = localSchema.Validate(newContext); valid &= localResults.IsValid; if (valid) { context.UpdateEvaluatedPropertiesAndItemsFromSubschemaValidation(newContext); } if (JsonSchemaOptions.OutputFormat == SchemaValidationOutputFormat.Flag) { if (!valid) { Log.Schema("Subschema failed; halting validation early"); break; } } else if (reportChildErrors) { nestedResults.Add(localResults); } } } else { Log.Schema($"No properties found that match regular expression \"{pattern}\""); } } results.IsValid = valid; if (reportChildErrors) { results.NestedResults = nestedResults; } if (!results.IsValid) { results.ErrorMessage = ErrorTemplate; } return(results); }
/// <summary> /// Provides the validation logic for this keyword. /// </summary> /// <param name="context">The context object.</param> /// <returns>Results object containing a final result and any errors that may have been found.</returns> public SchemaValidationResults Validate(SchemaValidationContext context) { var results = new SchemaValidationResults(Name, context); if (context.Instance.Type != JsonValueType.Array) { Log.Schema("Instance not an array; not applicable"); return(results); } var reportChildErrors = JsonSchemaOptions.ShouldReportChildErrors(this, context); var nestedResults = new List <SchemaValidationResults>(); var array = context.Instance.Array; var failedIndices = new JsonArray(); if (IsArray) { // have array of schemata: validate in sequence Log.Schema("items is an array; process elements index-aligned"); var i = 0; while (i < array.Count && i < Count) { var newContext = new SchemaValidationContext(context) { Instance = array[i], BaseRelativeLocation = context.BaseRelativeLocation?.CloneAndAppend(Name, i.ToString()), RelativeLocation = context.RelativeLocation.CloneAndAppend(Name, i.ToString()), InstanceLocation = context.InstanceLocation.CloneAndAppend(i.ToString()), }; var localResults = this[i].Validate(newContext); if (JsonSchemaOptions.OutputFormat == SchemaValidationOutputFormat.Flag && !localResults.IsValid) { Log.Schema("Subschema failed; halting validation early"); results.IsValid = false; break; } if (!localResults.IsValid) { failedIndices.Add(i); } else { context.LocallyValidatedIndices.Add(i); } if (reportChildErrors) { nestedResults.Add(this[i].Validate(newContext)); } context.LastEvaluatedIndex = Math.Max(context.LastEvaluatedIndex, i); context.LocalTierLastEvaluatedIndex = Math.Max(context.LocalTierLastEvaluatedIndex, i); context.UpdateEvaluatedPropertiesAndItemsFromSubschemaValidation(newContext); i++; } results.IsValid = nestedResults.All(r => r.IsValid); results.NestedResults = nestedResults; } else { Log.Schema("items is an single subschema; process all elements"); // have single schema: validate all against this var baseRelativeLocation = context.BaseRelativeLocation?.CloneAndAppend(Name); var relativeLocation = context.RelativeLocation.CloneAndAppend(Name); var valid = true; var i = 0; foreach (var jv in array) { var newContext = new SchemaValidationContext(context) { Instance = jv, BaseRelativeLocation = baseRelativeLocation, RelativeLocation = relativeLocation, InstanceLocation = context.InstanceLocation.CloneAndAppend(i.ToString()), }; var localResults = this[0].Validate(newContext); valid &= localResults.IsValid; if (!localResults.IsValid) { failedIndices.Add(i); } else { context.LocallyValidatedIndices.Add(i); } context.LastEvaluatedIndex = Math.Max(context.LastEvaluatedIndex, i); context.LocalTierLastEvaluatedIndex = Math.Max(context.LocalTierLastEvaluatedIndex, i); context.UpdateEvaluatedPropertiesAndItemsFromSubschemaValidation(newContext); if (JsonSchemaOptions.OutputFormat == SchemaValidationOutputFormat.Flag) { if (!valid) { Log.Schema("Subschema failed; halting validation early"); break; } } else if (reportChildErrors) { nestedResults.Add(localResults); } i++; } results.IsValid = valid; results.NestedResults = nestedResults; } if (!results.IsValid) { results.AdditionalInfo["indices"] = failedIndices; results.ErrorMessage = ErrorTemplate.ResolveTokens(results.AdditionalInfo); } return(results); }
/// <summary> /// Provides the validation logic for this keyword. /// </summary> /// <param name="context">The context object.</param> /// <returns>Results object containing a final result and any errors that may have been found.</returns> public SchemaValidationResults Validate(SchemaValidationContext context) { var results = new SchemaValidationResults(Name, context); if (context.Instance.Type != JsonValueType.Object) { Log.Schema("Instance not an object; not applicable"); return(results); } var valid = true; var reportChildErrors = JsonSchemaOptions.ShouldReportChildErrors(this, context); var obj = context.Instance.Object; var nestedResults = new List <SchemaValidationResults>(); foreach (var property in this) { if (!obj.ContainsKey(property.Key)) { Log.Schema($"Property {property.Key} not found; skipping"); continue; } context.EvaluatedPropertyNames.Add(property.Key); context.LocallyEvaluatedPropertyNames.Add(property.Key); var newContext = new SchemaValidationContext(context) { Instance = obj[property.Key], BaseRelativeLocation = context.BaseRelativeLocation?.CloneAndAppend(Name, property.Key), RelativeLocation = context.RelativeLocation.CloneAndAppend(Name, property.Key), InstanceLocation = context.InstanceLocation.CloneAndAppend(property.Key), }; var localResults = property.Value.Validate(newContext); context.EvaluatedPropertyNames.UnionWith(newContext.EvaluatedPropertyNames); context.EvaluatedPropertyNames.UnionWith(newContext.LocallyEvaluatedPropertyNames); valid &= localResults.IsValid; if (JsonSchemaOptions.OutputFormat == SchemaValidationOutputFormat.Flag) { if (!valid) { Log.Schema("Subschema failed; halting validation early"); break; } } else if (reportChildErrors) { nestedResults.Add(localResults); } } results.IsValid = valid; results.NestedResults = nestedResults; if (!results.IsValid) { results.ErrorMessage = ErrorTemplate; } return(results); }