protected override bool EvaluateTokenCore(JsonToken token, object value, int depth) { if (!GetChildrenAllValid(token, value, depth)) { List <int> invalidIndexes = new List <int>(); int index = 0; foreach (SchemaScope schemaScope in ChildScopes) { if (!schemaScope.IsValid) { invalidIndexes.Add(index); } else { ConditionalContext.TrackEvaluatedSchema(schemaScope.Schema); } index++; } IFormattable message = $"JSON does not match all schemas from 'allOf'. Invalid schema indexes: {StringHelpers.Join(", ", invalidIndexes)}."; RaiseError(message, ErrorType.AllOf, ParentSchemaScope.Schema, null, ConditionalContext.Errors); } else { for (int i = 0; i < ChildScopes.Count; i++) { ConditionalContext.TrackEvaluatedSchema(ChildScopes[i].Schema); } } return(true); }
public void Initialize(ContextBase context, SchemaScope parent, int initialDepth, ScopeType type) { base.Initialize(context, parent, initialDepth, type); ParentSchemaScope = parent; ConditionalContext = ConditionalContext.Create(context); }
protected override bool EvaluateTokenCore(JsonToken token, object value, int depth) { SchemaScope ifScope = GetSchemaScopeBySchema(If, token, value, depth); if (ifScope.IsValid) { if (Then != null) { SchemaScope thenScope = GetSchemaScopeBySchema(Then, token, value, depth); if (!thenScope.IsValid) { ConditionalContext context = (ConditionalContext)thenScope.Context; RaiseError($"JSON does not match schema from 'then'.", ErrorType.Then, Then, null, context.Errors); } } } else { if (Else != null) { SchemaScope elseScope = GetSchemaScopeBySchema(Else, token, value, depth); if (!elseScope.IsValid) { ConditionalContext context = (ConditionalContext)elseScope.Context; RaiseError($"JSON does not match schema from 'else'.", ErrorType.Else, Else, null, context.Errors); } } } return(true); }
protected override bool EvaluateTokenCore(JsonToken token, object?value, int depth) { if (TryGetChildrenAnyValid(token, value, depth, out bool anyValid)) { if (!anyValid) { RaiseError($"JSON does not match any schemas from 'anyOf'.", ErrorType.AnyOf, ParentSchemaScope.Schema, null, ConditionalContext.Errors); } // TODO: A little inefficent to find the valid children again foreach (SchemaScope childScope in ChildScopes) { if (childScope.IsValid) { ConditionalContext.TrackEvaluatedSchema(childScope.Schema); } } } else { RaiseCircularDependencyError(ErrorType.AnyOf); } return(true); }
public override void Initialize(ContextBase context, SchemaScope parent, int initialDepth, ScopeType type) { base.Initialize(context, parent, initialDepth, type); ChildScopes.Clear(); ParentSchemaScope = parent; ConditionalContext = ConditionalContext.Create(context, parent.ShouldValidateUnevaluated()); }
public override void Initialize(ContextBase context, SchemaScope parent, int initialDepth, ScopeType type) { base.Initialize(context, parent, initialDepth, type); If = null; Then = null; Else = null; ThenContext = null; ElseContext = null; }
protected override bool EvaluateTokenCore(JsonToken token, object?value, int depth) { if (!TryGetSchemaScopeBySchema(If !, token, value, depth, out SchemaScope? ifScope)) { RaiseCircularDependencyError(ErrorType.None); return(true); } if (ifScope.IsValid) { ConditionalContext.TrackEvaluatedSchema(ifScope.Schema); if (Then != null) { if (!TryGetSchemaScopeBySchema(Then, token, value, depth, out SchemaScope? thenScope)) { RaiseCircularDependencyError(ErrorType.Then); return(true); } if (!thenScope.IsValid) { RaiseError($"JSON does not match schema from 'then'.", ErrorType.Then, Then, null, thenScope.GetValidationErrors()); } else { ConditionalContext.TrackEvaluatedSchema(thenScope.Schema); } } } else { if (Else != null) { if (!TryGetSchemaScopeBySchema(Else, token, value, depth, out SchemaScope? elseScope)) { RaiseCircularDependencyError(ErrorType.Else); return(true); } if (!elseScope.IsValid) { RaiseError($"JSON does not match schema from 'else'.", ErrorType.Else, Else, null, elseScope.GetValidationErrors()); } else { ConditionalContext.TrackEvaluatedSchema(elseScope.Schema); } } } return(true); }
protected override bool EvaluateTokenCore(JsonToken token, object?value, int depth) { // If there is a recursive chain of $ref schemas then this will stack overflow. // If the ref scope is already evaluating then exit without checking children. if (_isReentrant) { return(true); } _isReentrant = true; try { if (TryGetChildrenAllValid(token, value, depth, out bool allValid)) { if (!allValid) { List <int> invalidIndexes = new List <int>(); int index = 0; foreach (SchemaScope schemaScope in ChildScopes) { if (!schemaScope.IsValid) { invalidIndexes.Add(index); } else { ConditionalContext.TrackEvaluatedSchema(schemaScope.Schema); } index++; } IFormattable message = $"JSON does not match schema from '$ref'."; RaiseError(message, ErrorType.Ref, ParentSchemaScope.Schema, null, ConditionalContext.Errors); } else { ConditionalContext.TrackEvaluatedSchema(ChildScopes[0].Schema); } } else { RaiseCircularDependencyError(ErrorType.Ref); } return(true); } finally { _isReentrant = false; } }
protected override bool EvaluateTokenCore(JsonToken token, object?value, int depth) { if (TryGetChildrenValidCount(token, value, depth, out int validCount)) { if (validCount != 1) { List <int> validIndexes = new List <int>(); int index = 0; foreach (SchemaScope schemaScope in ChildScopes) { if (schemaScope.IsValid) { validIndexes.Add(index); } index++; } IFormattable message; if (validIndexes.Count > 0) { message = $"JSON is valid against more than one schema from 'oneOf'. Valid schema indexes: {StringHelpers.Join(", ", validIndexes)}."; } else { message = $"JSON is valid against no schemas from 'oneOf'."; } RaiseError(message, ErrorType.OneOf, ParentSchemaScope.Schema, null, ConditionalContext.Errors); } else { // TODO: A little inefficent to find the valid child again foreach (SchemaScope childScope in ChildScopes) { if (childScope.IsValid) { ConditionalContext.TrackEvaluatedSchema(childScope.Schema); } } } } else { RaiseCircularDependencyError(ErrorType.OneOf); } return(true); }
protected override bool EvaluateTokenCore(JsonToken token, object?value, int depth) { if (Parent is ObjectScope objectScope) { var readProperties = objectScope.ReadProperties; ValidationUtils.Assert(readProperties != null); ValidationUtils.Assert(PropertyName != null); if (readProperties.Contains(PropertyName)) { if (TryGetChildrenAnyValid(token, value, depth, out bool anyValid)) { if (!anyValid) { RaiseError($"Dependencies for property '{PropertyName}' failed.", ErrorType.Dependencies, ParentSchemaScope.Schema, null, ConditionalContext.Errors); } else { foreach (SchemaScope childScope in ChildScopes) { if (childScope.IsValid) { ConditionalContext.TrackEvaluatedSchema(childScope.Schema); } } } } else { RaiseCircularDependencyError(ErrorType.Dependencies); } } } return(true); }
public static SchemaScope CreateTokenScope(JsonToken token, JSchema schema, ContextBase context, SchemaScope parent, int depth) { SchemaScope scope; switch (token) { case JsonToken.StartObject: ObjectScope objectScope = context.Validator.GetCachedScope <ObjectScope>(ScopeType.Object); if (objectScope == null) { objectScope = new ObjectScope(); } objectScope.Initialize(context, parent, depth, schema); context.Scopes.Add(objectScope); objectScope.InitializeScopes(token); scope = objectScope; break; case JsonToken.StartArray: case JsonToken.StartConstructor: ArrayScope arrayScope = context.Validator.GetCachedScope <ArrayScope>(ScopeType.Array); if (arrayScope == null) { arrayScope = new ArrayScope(); } arrayScope.Initialize(context, parent, depth, schema); context.Scopes.Add(arrayScope); scope = arrayScope; break; default: PrimativeScope primativeScope = context.Validator.GetCachedScope <PrimativeScope>(ScopeType.Primitive); if (primativeScope == null) { primativeScope = new PrimativeScope(); } primativeScope.Initialize(context, parent, depth, schema); scope = primativeScope; context.Scopes.Add(scope); break; } if (!schema._allOf.IsNullOrEmpty()) { AllOfScope allOfScope = context.Validator.GetCachedScope <AllOfScope>(ScopeType.AllOf); if (allOfScope == null) { allOfScope = new AllOfScope(); } allOfScope.Initialize(context, scope, depth, ScopeType.AllOf); scope.AddChildScope(allOfScope); allOfScope.InitializeScopes(token, schema._allOf.GetInnerList(), context.Scopes.Count - 1); } if (!schema._anyOf.IsNullOrEmpty()) { AnyOfScope anyOfScope = context.Validator.GetCachedScope <AnyOfScope>(ScopeType.AnyOf); if (anyOfScope == null) { anyOfScope = new AnyOfScope(); } anyOfScope.Initialize(context, scope, depth, ScopeType.AnyOf); scope.AddChildScope(anyOfScope); anyOfScope.InitializeScopes(token, schema._anyOf.GetInnerList(), context.Scopes.Count - 1); } if (!schema._oneOf.IsNullOrEmpty()) { OneOfScope oneOfScope = context.Validator.GetCachedScope <OneOfScope>(ScopeType.OneOf); if (oneOfScope == null) { oneOfScope = new OneOfScope(); } oneOfScope.Initialize(context, scope, depth, ScopeType.OneOf); scope.AddChildScope(oneOfScope); oneOfScope.InitializeScopes(token, schema._oneOf.GetInnerList(), context.Scopes.Count - 1); } if (schema.Not != null) { NotScope notScope = context.Validator.GetCachedScope <NotScope>(ScopeType.Not); if (notScope == null) { notScope = new NotScope(); } notScope.Initialize(context, scope, depth, ScopeType.Not); scope.AddChildScope(notScope); notScope.InitializeScopes(token, new List <JSchema> { schema.Not }, context.Scopes.Count - 1); } // only makes sense to eval if/then/else when there is an if and either a then or a else if (schema.If != null && (schema.Then != null || schema.Else != null)) { IfThenElseScope ifThenElseScope = context.Validator.GetCachedScope <IfThenElseScope>(ScopeType.IfThenElse); if (ifThenElseScope == null) { ifThenElseScope = new IfThenElseScope(); } ifThenElseScope.Initialize(context, scope, depth, ScopeType.IfThenElse); scope.AddChildScope(ifThenElseScope); ifThenElseScope.If = schema.If; if (schema.Then != null) { ifThenElseScope.Then = schema.Then; ifThenElseScope.ThenContext = ConditionalContext.Create(context); } if (schema.Else != null) { ifThenElseScope.Else = schema.Else; ifThenElseScope.ElseContext = ConditionalContext.Create(context); } ifThenElseScope.InitializeScopes(token, context.Scopes.Count - 1); } return(scope); }
public void InitializeScopes(JsonToken token) { if (!Schema._dependencies.IsNullOrEmpty()) { foreach (KeyValuePair <string, object> dependency in Schema._dependencies.GetInnerDictionary()) { JSchema dependencySchema = dependency.Value as JSchema; if (dependencySchema != null) { SchemaScope scope = CreateTokenScope(token, dependencySchema, ConditionalContext.Create(Context), null, InitialDepth); _dependencyScopes.Add(dependency.Key, scope); } } } }
protected ConditionalScope(ContextBase context, SchemaScope parent, int initialDepth) : base(context, parent, initialDepth) { ParentSchemaScope = parent; ConditionalContext = ConditionalContext.Create(context); }
public ConditionalContext CreateConditionalContext() { return(ConditionalContext.Create(Context, ShouldValidateUnevaluated())); }
protected override bool EvaluateTokenCore(JsonToken token, object value, int depth) { int relativeDepth = depth - InitialDepth; if (relativeDepth == 0) { EnsureEnum(token, value); switch (token) { case JsonToken.StartArray: EnsureValid(value); TestType(Schema, JSchemaType.Array); return(false); case JsonToken.StartConstructor: JSchemaType schemaType = Schema.Type.GetValueOrDefault(JSchemaType.None); if (schemaType != JSchemaType.None) { RaiseError($"Invalid type. Expected {schemaType.GetDisplayText()} but got Constructor.", ErrorType.Type, Schema, value, null); } return(false); case JsonToken.EndArray: case JsonToken.EndConstructor: ValidateConditionalChildren(token, value, depth); int itemCount = _index + 1; if (Schema.MaximumItems != null && itemCount > Schema.MaximumItems) { RaiseError($"Array item count {itemCount} exceeds maximum count of {Schema.MaximumItems}.", ErrorType.MaximumItems, Schema, itemCount, null); } if (Schema.MinimumItems != null && itemCount < Schema.MinimumItems) { RaiseError($"Array item count {itemCount} is less than minimum count of {Schema.MinimumItems}.", ErrorType.MinimumItems, Schema, itemCount, null); } if (Schema.Contains != null) { // MinimumContains overrides default contains behavior if (Schema.MinimumContains != null) { if (_matchCount < Schema.MinimumContains) { RaiseError($"Contains match count {_matchCount} is less than minimum contains count of {Schema.MinimumContains}.", ErrorType.MinimumContains, Schema, null, GetValidationErrors(_containsContexts)); } } else { if (_matchCount == 0) { RaiseError($"No items match contains.", ErrorType.Contains, Schema, null, GetValidationErrors(_containsContexts)); } } if (_matchCount > Schema.MaximumContains) { RaiseError($"Contains match count {_matchCount} exceeds maximum contains count of {Schema.MaximumContains}.", ErrorType.MaximumContains, Schema, null, GetValidationErrors(_containsContexts)); } } if (!_unevaluatedScopes.IsNullOrEmpty()) { foreach (KeyValuePair <int, UnevaluatedContext> item in _unevaluatedScopes) { if (!item.Value.Evaluated) { IFormattable message = $"Item at index {item.Key} has not been successfully evaluated and the schema does not allow unevaluated items."; RaiseError(message, ErrorType.UnevaluatedItems, Schema, item.Key, item.Value.SchemaScope.GetValidationErrors()); } } } return(true); default: throw new InvalidOperationException("Unexpected token when evaluating array: " + token); } } if (relativeDepth == 1) { if (JsonTokenHelpers.IsPrimitiveOrStartToken(token)) { _index++; if (Schema.UniqueItems || !Schema._validators.IsNullOrEmpty()) { if (Context.TokenWriter == null) { Context.TokenWriter = new JTokenWriter(); Context.TokenWriter.WriteToken(token, value); } } bool matched = false; if (Schema.ItemsPositionValidation) { // TODO: Remove LINQ JSchema itemSchema = Schema._items?.ElementAtOrDefault(_index); if (itemSchema != null) { CreateScopesAndEvaluateToken(token, value, depth, itemSchema); matched = true; } else { if (!Schema.AllowAdditionalItems) { RaiseError($"Index {_index + 1} has not been defined and the schema does not allow additional items.", ErrorType.AdditionalItems, Schema, value, null); } else if (Schema.AdditionalItems != null) { CreateScopesAndEvaluateToken(token, value, depth, Schema.AdditionalItems); matched = true; } } } else { if (!Schema._items.IsNullOrEmpty()) { CreateScopesAndEvaluateToken(token, value, depth, Schema._items[0]); matched = true; } } if (ShouldEvaluateContains()) { ConditionalContext containsContext = CreateConditionalContext(); _containsContexts.Add(containsContext); // contains scope should not have the current scope the parent // do not want contain failures setting the current scope's IsValid CreateScopesAndEvaluateToken(token, value, depth, Schema.Contains, null, containsContext); } if (!matched) { if (ShouldValidateUnevaluated()) { _unevaluatedScopes[_index] = Schema.UnevaluatedItems != null ? new UnevaluatedContext(CreateScopesAndEvaluateToken(token, value, depth, Schema.UnevaluatedItems, this, CreateConditionalContext())) : new UnevaluatedContext(AlwaysFalseScope.Instance); } } } if (JsonTokenHelpers.IsPrimitiveOrEndToken(token)) { if (Schema.UniqueItems) { JToken currentToken = Context.TokenWriter.CurrentToken; bool isDuplicate = JsonTokenHelpers.Contains(_uniqueArrayItems, currentToken); if (isDuplicate) { object v = (currentToken is JValue valueToken) ? valueToken.Value : currentToken; RaiseError($"Non-unique array item at index {_index}.", ErrorType.UniqueItems, Schema, v, null); } else { _uniqueArrayItems.Add(Context.TokenWriter.CurrentToken); } } if (ShouldEvaluateContains()) { ConditionalContext currentContainsContext = _containsContexts[_containsContexts.Count - 1]; if (!currentContainsContext.HasErrors) { _matchCount++; } } if (ShouldValidateUnevaluated() && _unevaluatedScopes.TryGetValue(_index, out UnevaluatedContext unevaluatedContext)) { // Property is valid against unevaluatedItems schema so no need to search further bool isValid = unevaluatedContext.SchemaScope.IsValid; unevaluatedContext.Evaluated = isValid; if (!isValid) { for (int i = Context.Scopes.Count - 1; i >= 0; i--) { Scope scope = Context.Scopes[i]; if (scope.InitialDepth == InitialDepth + 1) { // Schema for a item if (scope.Parent != null && scope is SchemaScope schemaScope && schemaScope.IsValid) { unevaluatedContext.AddValidScope(schemaScope.Parent.Schema); } } else if (scope.InitialDepth == InitialDepth) { // Schema for the current array. // Need to check these for oneOf, allOf, etc. if (scope is SchemaScope schemaScope) { if (schemaScope.Schema._allowAdditionalItems.GetValueOrDefault() || schemaScope.Schema.AdditionalItems != null || schemaScope.Schema.AllowUnevaluatedItems.GetValueOrDefault()) { unevaluatedContext.AddValidScope(schemaScope.Schema); } } } else if (scope.InitialDepth < InitialDepth) { break; } } } } } } return(false); }
protected override bool EvaluateTokenCore(JsonToken token, object value, int depth) { int relativeDepth = depth - InitialDepth; if (relativeDepth == 0) { EnsureEnum(token, value); switch (token) { case JsonToken.StartArray: EnsureValid(value); TestType(Schema, JSchemaType.Array); return(false); case JsonToken.StartConstructor: JSchemaType schemaType = Schema.Type.GetValueOrDefault(JSchemaType.None); if (schemaType != JSchemaType.None) { RaiseError($"Invalid type. Expected {schemaType.GetDisplayText()} but got Constructor.", ErrorType.Type, Schema, value, null); } return(false); case JsonToken.EndArray: case JsonToken.EndConstructor: ValidateConditionalChildren(token, value, depth); int itemCount = _index + 1; if (Schema.MaximumItems != null && itemCount > Schema.MaximumItems) { RaiseError($"Array item count {itemCount} exceeds maximum count of {Schema.MaximumItems}.", ErrorType.MaximumItems, Schema, itemCount, null); } if (Schema.MinimumItems != null && itemCount < Schema.MinimumItems) { RaiseError($"Array item count {itemCount} is less than minimum count of {Schema.MinimumItems}.", ErrorType.MinimumItems, Schema, itemCount, null); } if (Schema.Contains != null && !_matchContains) { List <ValidationError> containsErrors = new List <ValidationError>(); foreach (ConditionalContext containsContext in _containsContexts) { containsErrors.AddRange(containsContext.Errors); } RaiseError($"No items match contains.", ErrorType.Contains, Schema, null, containsErrors); } return(true); default: throw new InvalidOperationException("Unexpected token when evaluating array: " + token); } } if (relativeDepth == 1) { if (JsonTokenHelpers.IsPrimitiveOrStartToken(token)) { _index++; if (Schema.UniqueItems || !Schema._validators.IsNullOrEmpty()) { if (Context.TokenWriter == null) { Context.TokenWriter = new JTokenWriter(); Context.TokenWriter.WriteToken(token, value); } } if (Schema.ItemsPositionValidation) { JSchema itemSchema = Schema._items?.ElementAtOrDefault(_index); if (itemSchema != null) { CreateScopesAndEvaluateToken(token, value, depth, itemSchema); } else { if (!Schema.AllowAdditionalItems) { RaiseError($"Index {_index + 1} has not been defined and the schema does not allow additional items.", ErrorType.AdditionalItems, Schema, value, null); } else if (Schema.AdditionalItems != null) { CreateScopesAndEvaluateToken(token, value, depth, Schema.AdditionalItems); } } } else { if (!Schema._items.IsNullOrEmpty()) { CreateScopesAndEvaluateToken(token, value, depth, Schema._items[0]); } } // no longer need to check contains schema after match if (Schema.Contains != null && !_matchContains) { ConditionalContext containsContext = ConditionalContext.Create(Context); _containsContexts.Add(containsContext); // contains scope should not have the current scope the parent // do not want contain failures setting the current scope's IsValid CreateScopesAndEvaluateToken(token, value, depth, Schema.Contains, null, containsContext); } } if (JsonTokenHelpers.IsPrimitiveOrEndToken(token)) { if (Schema.UniqueItems) { JToken currentToken = Context.TokenWriter.CurrentToken; bool isDuplicate = JsonTokenHelpers.Contains(_uniqueArrayItems, currentToken); if (isDuplicate) { object v = (currentToken is JValue valueToken) ? valueToken.Value : currentToken; RaiseError($"Non-unique array item at index {_index}.", ErrorType.UniqueItems, Schema, v, null); } else { _uniqueArrayItems.Add(Context.TokenWriter.CurrentToken); } } if (Schema.Contains != null && !_matchContains) { ConditionalContext currentContainsContext = _containsContexts[_containsContexts.Count - 1]; if (!currentContainsContext.HasErrors) { _matchContains = true; // no longer need previous errors after match _containsContexts.Clear(); } } } } return(false); }
private void InitializeScope(JsonToken token, int scopeIndex, JSchema schema, ConditionalContext context) { // cache this for performance int scopeCurrentIndex = scopeIndex; // check to see whether a scope with the same schema exists SchemaScope childScope = GetExistingSchemaScope(schema, ref scopeCurrentIndex); if (childScope == null) { childScope = SchemaScope.CreateTokenScope(token, schema, context, null, InitialDepth); } #if DEBUG childScope.ConditionalParents.Add(this); #endif ChildScopes.Add(childScope); }
protected override bool EvaluateTokenCore(JsonToken token, object?value, int depth) { int relativeDepth = depth - InitialDepth; if (relativeDepth == 0) { EnsureEnum(token, value); switch (token) { case JsonToken.StartArray: EnsureValid(value); TestType(Schema, JSchemaType.Array); return(false); case JsonToken.StartConstructor: JSchemaType schemaType = Schema.Type.GetValueOrDefault(JSchemaType.None); if (schemaType != JSchemaType.None) { RaiseError($"Invalid type. Expected {schemaType.GetDisplayText()} but got Constructor.", ErrorType.Type, Schema, value, null); } return(false); case JsonToken.EndArray: case JsonToken.EndConstructor: ValidateConditionalChildren(token, value, depth); int itemCount = _index + 1; if (Schema.MaximumItems != null && itemCount > Schema.MaximumItems) { RaiseError($"Array item count {itemCount} exceeds maximum count of {Schema.MaximumItems}.", ErrorType.MaximumItems, Schema, itemCount, null); } if (Schema.MinimumItems != null && itemCount < Schema.MinimumItems) { RaiseError($"Array item count {itemCount} is less than minimum count of {Schema.MinimumItems}.", ErrorType.MinimumItems, Schema, itemCount, null); } if (Schema.Contains != null) { ValidationUtils.Assert(_containsContexts != null); // MinimumContains overrides default contains behavior if (Schema.MinimumContains != null) { if (_matchCount < Schema.MinimumContains) { RaiseError($"Contains match count {_matchCount} is less than minimum contains count of {Schema.MinimumContains}.", ErrorType.MinimumContains, Schema, null, GetValidationErrors(_containsContexts)); } } else { if (_matchCount == 0) { RaiseError($"No items match contains.", ErrorType.Contains, Schema, null, GetValidationErrors(_containsContexts)); } } if (_matchCount > Schema.MaximumContains) { RaiseError($"Contains match count {_matchCount} exceeds maximum contains count of {Schema.MaximumContains}.", ErrorType.MaximumContains, Schema, null, GetValidationErrors(_containsContexts)); } } if (!_unevaluatedScopes.IsNullOrEmpty()) { foreach (KeyValuePair <int, UnevaluatedContext> item in _unevaluatedScopes) { if (!item.Value.Evaluated) { IFormattable message = $"Item at index {item.Key} has not been successfully evaluated and the schema does not allow unevaluated items."; RaiseError(message, ErrorType.UnevaluatedItems, Schema, item.Key, item.Value.SchemaScope.GetValidationErrors()); } } } return(true); default: throw new InvalidOperationException("Unexpected token when evaluating array: " + token); } } if (relativeDepth == 1) { if (JsonTokenHelpers.IsPrimitiveOrStartToken(token)) { _index++; if (Schema.UniqueItems || !Schema._validators.IsNullOrEmpty()) { if (Context.TokenWriter == null) { Context.TokenWriter = new JTokenWriter(); Context.TokenWriter.WriteToken(token, value); } } bool matched = false; if (Schema.ItemsPositionValidation) { // TODO: Remove LINQ JSchema?itemSchema = Schema._items?.ElementAtOrDefault(_index); if (itemSchema != null) { CreateScopesAndEvaluateToken(token, value, depth, itemSchema); matched = true; } else { if (!Schema.AllowAdditionalItems) { RaiseError($"Index {_index + 1} has not been defined and the schema does not allow additional items.", ErrorType.AdditionalItems, Schema, value, null); } else if (Schema.AdditionalItems != null) { CreateScopesAndEvaluateToken(token, value, depth, Schema.AdditionalItems); matched = true; } } } else { if (!Schema._items.IsNullOrEmpty()) { CreateScopesAndEvaluateToken(token, value, depth, Schema._items[0]); matched = true; } } if (ShouldEvaluateContains()) { ConditionalContext containsContext = CreateConditionalContext(); _containsContexts.Add(containsContext); // contains scope should not have the current scope the parent // do not want contain failures setting the current scope's IsValid CreateScopesAndEvaluateToken(token, value, depth, Schema.Contains !, null, containsContext); } if (!matched) { if (ShouldValidateUnevaluated()) { _unevaluatedScopes ![_index] = Schema.UnevaluatedItems != null