Exemplo n.º 1
0
        protected bool TestType <T>(JSchema currentSchema, JSchemaType currentType, T value)
        {
            if (!JSchemaTypeHelpers.HasFlag(currentSchema.Type, currentType))
            {
                RaiseError($"Invalid type. Expected {currentSchema.Type.Value.GetDisplayText()} but got {currentType.GetDisplayText()}.", ErrorType.Type, currentSchema, value, null);
                return(false);
            }

            return(true);
        }
        internal static bool TestType <T>(SchemaScope scope, JSchema currentSchema, JSchemaType currentType, T?value)
        {
            if (!JSchemaTypeHelpers.HasFlag(currentSchema.Type, currentType))
            {
                scope.RaiseError($"Invalid type. Expected {currentSchema.Type.GetValueOrDefault().GetDisplayText()} but got {currentType.GetDisplayText()}.", ErrorType.Type, currentSchema, value, null);
                return(false);
            }

            return(true);
        }
Exemplo n.º 3
0
        protected override bool EvaluateTokenCore(JsonToken token, object value, int depth)
        {
            switch (token)
            {
            case JsonToken.Integer:
            {
                if (!ValidateInteger(Schema, value))
                {
                    return(true);
                }
                break;
            }

            case JsonToken.Float:
            {
                if (!ValidateNumber(Schema, value))
                {
                    return(true);
                }
                break;
            }

            case JsonToken.String:
            {
                Uri    uri = value as Uri;
                string s   = (uri != null) ? uri.OriginalString : value.ToString();

                if (!ValidateString(Schema, s))
                {
                    return(true);
                }
                break;
            }

            case JsonToken.Boolean:
            {
                if (!ValidateBoolean(Schema, value))
                {
                    return(true);
                }
                break;
            }

            case JsonToken.Null:
            {
                if (!ValidateNull(Schema, value))
                {
                    return(true);
                }
                break;
            }

            case JsonToken.Bytes:
            {
                byte[] data = value as byte[];
                if (data == null)
                {
                    data = ((Guid)value).ToByteArray();
                }

                string s = Convert.ToBase64String(data);
                if (!ValidateString(Schema, s))
                {
                    return(true);
                }
                break;
            }

            case JsonToken.Undefined:
            {
                JSchemaType schemaType = Schema.Type.GetValueOrDefault(JSchemaType.None);

                if (schemaType != JSchemaType.None)
                {
                    RaiseError($"Invalid type. Expected {schemaType.GetDisplayText()} but got {token}.", ErrorType.Type, Schema, value, null);
                }
                break;
            }

            default:
            {
                throw new ArgumentOutOfRangeException("Unexpected token: " + token);
            }
            }

            EnsureEnum(token, value);

            return(true);
        }
        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);
        }
Exemplo n.º 5
0
        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);
        }
        protected override bool EvaluateTokenCore(JsonToken token, object value, int depth)
        {
            EnsureValid(value);

            switch (token)
            {
            case JsonToken.Integer:
            {
                if (!ValidateInteger(Schema, value))
                {
                    return(true);
                }
                break;
            }

            case JsonToken.Float:
            {
                if (!ValidateNumber(Schema, value))
                {
                    return(true);
                }
                break;
            }

            case JsonToken.String:
            case JsonToken.PropertyName:
            {
                if (value == null)
                {
                    // This can happen with a JTokenReader when a JValue has a String type
                    // and a null value
                    goto case JsonToken.Null;
                }

                string s = (value is Uri uri) ? uri.OriginalString : value.ToString();

                if (!ValidateString(this, Schema, s))
                {
                    return(true);
                }
                break;
            }

            case JsonToken.Boolean:
            {
                if (!ValidateBoolean(Schema, value))
                {
                    return(true);
                }
                break;
            }

            case JsonToken.Null:
            {
                if (!ValidateNull(Schema, value))
                {
                    return(true);
                }
                break;
            }

            case JsonToken.Bytes:
            {
                byte[] data = value as byte[];
                if (data == null)
                {
                    data = ((Guid)value).ToByteArray();
                }

                string s = Convert.ToBase64String(data);
                if (!ValidateString(this, Schema, s))
                {
                    return(true);
                }
                break;
            }

            case JsonToken.Undefined:
            {
                JSchemaType schemaType = Schema.Type.GetValueOrDefault(JSchemaType.None);

                if (schemaType != JSchemaType.None)
                {
                    RaiseError($"Invalid type. Expected {schemaType.GetDisplayText()} but got {token}.", ErrorType.Type, Schema, value, null);
                }
                break;
            }

            default:
            {
                throw new ArgumentOutOfRangeException("Unexpected token: " + token);
            }
            }

            EnsureEnum(token, value);
            ValidateConditionalChildren(token, value, depth);

            return(true);
        }
Exemplo n.º 7
0
        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
Exemplo n.º 8
0
        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:
                    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:
                    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);
                    }

                    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 != null)
                            ? Schema._items.ElementAtOrDefault(_index)
                            : null;

                        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]);
                        }
                    }
                }

                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) ? ((JValue)currentToken).Value : currentToken;

                            RaiseError($"Non-unique array item at index {_index}.", ErrorType.UniqueItems, Schema, v, null);
                        }
                        else
                        {
                            _uniqueArrayItems.Add(Context.TokenWriter.CurrentToken);
                        }
                    }
                }
            }

            return(false);
        }