public static void AssertSingleProperty(JSchema schema, string propertyName, JSchemaType schemaType, bool required = true)
 {
     Assert.IsNotNull(schema);
     Assert.IsNotNull(schema.Properties);
     Assert.IsTrue(schema.Properties.ContainsKey(propertyName), string.Format("property with name '{0}' expected.", propertyName));
     Assert.IsNotNull(schema.Properties[propertyName].Type);
     Assert.AreEqual(schemaType, schema.Properties[propertyName].Type.Value);
     if (required)
         Assert.IsTrue(schema.Required.Contains(propertyName), "Property {0} should be required", propertyName);
 }
Exemple #2
0
        private bool CanConvert(JSchemaType? type, JSchemaType? typeBase)
        {
            if (!type.HasValue)
                return true;

            if ((type.Value != JSchemaType.Object && type.Value != JSchemaType.Array)
                && (typeBase.Value == JSchemaType.Object || typeBase.Value == JSchemaType.Array))
                return false;

            return true;
        }
        internal static bool HasFlag(JSchemaType? value, JSchemaType flag)
        {
            // default value is Any
            if (value == null)
                return true;

            bool match = ((value & flag) == flag);
            if (match)
                return true;

            // integer is a subset of number
            if (flag == JSchemaType.Integer && (value & JSchemaType.Number) == JSchemaType.Number)
                return true;

            return false;
        }
 public EdmPrimitiveTypeKind ToEdmPrimitiveType(JSchemaType type)
 {
     switch (type)
     {
         case JSchemaType.String:
             return EdmPrimitiveTypeKind.String;
         case JSchemaType.Number:
             return EdmPrimitiveTypeKind.Double;
         case JSchemaType.Integer:
             return EdmPrimitiveTypeKind.Int32;
         case JSchemaType.Boolean:
             return EdmPrimitiveTypeKind.Boolean;
         case JSchemaType.None:
         case JSchemaType.Object:
         case JSchemaType.Array:
         case JSchemaType.Null:
         default:
             throw new ArgumentOutOfRangeException(nameof(type), type, null);
     }
 }
Exemple #5
0
        private void WriteType(string propertyName, JsonWriter writer, JSchemaType type)
        {
            if (Enum.IsDefined(typeof(JSchemaType), type))
            {
                writer.WritePropertyName(propertyName);
                writer.WriteValue(JSchemaTypeHelpers.MapType(type));
            }
            else
            {
                // Known to not need disposing.
                var en = EnumUtils.GetFlagsValues(type).Where(v => v != JSchemaType.None).GetEnumerator();
                if (!en.MoveNext())
                {
                    return;
                }

                writer.WritePropertyName(propertyName);

                var first = en.Current;

                if (en.MoveNext())
                {
                    writer.WriteStartArray();
                    writer.WriteValue(JSchemaTypeHelpers.MapType(first));
                    do
                    {
                        writer.WriteValue(JSchemaTypeHelpers.MapType(en.Current));
                    } while (en.MoveNext());

                    writer.WriteEndArray();
                }
                else
                {
                    writer.WriteValue(JSchemaTypeHelpers.MapType(first));
                }
            }
        }
Exemple #6
0
        private void WriteType(string propertyName, JsonWriter writer, JSchemaType type)
        {
            IList <JSchemaType> types;

            if (Enum.IsDefined(typeof(JSchemaType), type))
            {
                types = new List <JSchemaType> {
                    type
                }
            }
            ;
            else
            {
                types = EnumUtils.GetFlagsValues(type).Where(v => v != JSchemaType.None).ToList();
            }

            if (types.Count == 0)
            {
                return;
            }

            writer.WritePropertyName(propertyName);

            if (types.Count == 1)
            {
                writer.WriteValue(JSchemaTypeHelpers.MapType(types[0]));
                return;
            }

            writer.WriteStartArray();
            foreach (JSchemaType schemaType in types)
            {
                writer.WriteValue(JSchemaTypeHelpers.MapType(schemaType));
            }
            writer.WriteEndArray();
        }
Exemple #7
0
        public JsonMapper_old(List <IASTNode> parseTree)
        {
            var schemas = new List <JSchema>();

            foreach (var node in parseTree)
            {
                if (node is ASTType)
                {
                    var     t      = node as ASTType;
                    JSchema schema = new JSchema
                    {
                        Title       = t.Name,
                        Description = Annotate(t.Annotations),
                        Type        = JSchemaType.Object
                    };
                    JSchema properties = new JSchema {
                    };

                    List <string> requiredFields = new List <string>();
                    foreach (var field in t.Fields)
                    {
                        var _mode = field.Type.First().Value;
                        var _type = field.Type.Last().Value;

                        if (_mode != "List")
                        {
                            JSchemaType fieldType = ConvertToJsonType(_type);
                            schema.Properties.Add(
                                field.Name,
                                new JSchema
                            {
                                Description = Annotate(field.Annotations),
                                Type        = fieldType
                            });
                        }
                        else
                        {
                            JSchemaType fieldType = JSchemaType.Array;
                            JSchema     list      = new JSchema
                            {
                                Description = Annotate(field.Annotations),
                                Type        = fieldType
                            };
                            list.Items.Add(new JSchema
                            {
                                Type = ConvertToJsonType(_type)
                            });
                            schema.Properties.Add(field.Name, list);
                        }

                        bool nullable = field.Type.First().Value == "Maybe";
                        if (!nullable)
                        {
                            schema.Required.Add(field.Name);
                        }
                    }

                    schemas.Add(schema);
                }
            }
        }
Exemple #8
0
 public void IgnoreNonDateTimeSchema(JSchemaType type, string format = null)
 {
     Sut.EnsureIgnore(new JSchema {
         Type = type, Format = format
     });
 }
Exemple #9
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);
        }
Exemple #10
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);
        }
        private void PopulateSchema(JSchema schema, JsonContract contract, JsonProperty memberProperty, Required valueRequired)
        {
            schema.Title       = GetTitle(contract.NonNullableUnderlyingType);
            schema.Description = GetDescription(contract.NonNullableUnderlyingType);

            JsonConverter converter;

            if (contract.Converter != null && contract.Converter.CanWrite)
            {
                converter = contract.Converter;
            }
            else if (contract.InternalConverter != null && contract.InternalConverter.CanWrite)
            {
                converter = contract.InternalConverter;
            }
            else
            {
                converter = null;
            }

            if (converter != null)
            {
                schema.Type = null;
            }
            else
            {
                switch (contract.ContractType)
                {
                case JsonContractType.Object:
                    if (contract.NonNullableUnderlyingType == typeof(object))
                    {
                        PopulatePrimativeSchema(schema, contract, memberProperty, valueRequired);
                    }
                    else
                    {
                        if (schema.Id == null)
                        {
                            schema.Id = GetTypeId(contract.NonNullableUnderlyingType, false);
                        }

                        schema.Type = AddNullType(JSchemaType.Object, valueRequired);
                        GenerateObjectSchema(schema, contract.NonNullableUnderlyingType, (JsonObjectContract)contract);
                    }
                    break;

                case JsonContractType.Array:
                    if (schema.Id == null)
                    {
                        schema.Id = GetTypeId(contract.NonNullableUnderlyingType, false);
                    }

                    schema.Type         = AddNullType(JSchemaType.Array, valueRequired);
                    schema.MinimumItems = DataAnnotationHelpers.GetMinLength(memberProperty);
                    schema.MaximumItems = DataAnnotationHelpers.GetMaxLength(memberProperty);

                    JsonArrayAttribute arrayAttribute = JsonTypeReflector.GetCachedAttribute <JsonArrayAttribute>(contract.NonNullableUnderlyingType);

                    Required?required = null;
                    if (arrayAttribute != null && !arrayAttribute.AllowNullItems)
                    {
                        required = Required.Always;
                    }

                    Type collectionItemType = ReflectionUtils.GetCollectionItemType(contract.NonNullableUnderlyingType);
                    if (collectionItemType != null)
                    {
                        schema.Items.Add(GenerateInternal(collectionItemType, required, null, (JsonArrayContract)contract, null));
                    }
                    break;

                case JsonContractType.Primitive:
                    PopulatePrimativeSchema(schema, contract, memberProperty, valueRequired);
                    break;

                case JsonContractType.String:
                    JSchemaType schemaType = (!ReflectionUtils.IsNullable(contract.UnderlyingType))
                            ? JSchemaType.String
                            : AddNullType(JSchemaType.String, valueRequired);

                    schema.Type          = schemaType;
                    schema.MinimumLength = DataAnnotationHelpers.GetMinLength(memberProperty);
                    schema.MaximumLength = DataAnnotationHelpers.GetMaxLength(memberProperty);
                    break;

                case JsonContractType.Dictionary:
                    schema.Type = AddNullType(JSchemaType.Object, valueRequired);
                    schema.MinimumProperties = DataAnnotationHelpers.GetMinLength(memberProperty);
                    schema.MaximumProperties = DataAnnotationHelpers.GetMaxLength(memberProperty);

                    Type keyType;
                    Type valueType;
                    ReflectionUtils.GetDictionaryKeyValueTypes(contract.NonNullableUnderlyingType, out keyType, out valueType);

                    if (keyType != null)
                    {
                        JsonContract keyContract = _generator.ContractResolver.ResolveContract(keyType);

                        // can be converted to a string
                        if (keyContract.ContractType == JsonContractType.Primitive)
                        {
                            schema.AdditionalProperties = GenerateInternal(valueType, _generator.DefaultRequired, null, (JsonDictionaryContract)contract, null);
                        }
                    }
                    break;

                case JsonContractType.Serializable:
                    if (schema.Id == null)
                    {
                        schema.Id = GetTypeId(contract.NonNullableUnderlyingType, false);
                    }

                    schema.Type = AddNullType(JSchemaType.Object, valueRequired);
                    schema.AllowAdditionalProperties = true;
                    break;

                case JsonContractType.Dynamic:
                case JsonContractType.Linq:
                    schema.Type = null;
                    break;

                default:
                    throw new JSchemaException("Unexpected contract type: {0}".FormatWith(CultureInfo.InvariantCulture, contract));
                }
            }
        }
        private JSchemaType GetJSchemaType(Type type, Required valueRequired)
        {
            JSchemaType schemaType = JSchemaType.None;

            if (ReflectionUtils.IsNullable(type))
            {
                if (valueRequired == Required.Default || valueRequired == Required.AllowNull)
                {
                    schemaType = JSchemaType.Null;
                }

                if (ReflectionUtils.IsNullableType(type))
                {
                    type = Nullable.GetUnderlyingType(type);
                }
            }

            PrimitiveTypeCode typeCode = ConvertUtils.GetTypeCode(type);

            switch (typeCode)
            {
            case PrimitiveTypeCode.Empty:
            case PrimitiveTypeCode.Object:
                return(schemaType | JSchemaType.String | JSchemaType.Boolean | JSchemaType.Integer | JSchemaType.Number | JSchemaType.Object | JSchemaType.Array);

            case PrimitiveTypeCode.DBNull:
                return(schemaType | JSchemaType.Null);

            case PrimitiveTypeCode.Boolean:
                return(schemaType | JSchemaType.Boolean);

            case PrimitiveTypeCode.Char:
                return(schemaType | JSchemaType.String);

            case PrimitiveTypeCode.SByte:
            case PrimitiveTypeCode.Byte:
            case PrimitiveTypeCode.Int16:
            case PrimitiveTypeCode.UInt16:
            case PrimitiveTypeCode.Int32:
            case PrimitiveTypeCode.UInt32:
            case PrimitiveTypeCode.Int64:
            case PrimitiveTypeCode.UInt64:
            case PrimitiveTypeCode.BigInteger:
                return(schemaType | JSchemaType.Integer);

            case PrimitiveTypeCode.Single:
            case PrimitiveTypeCode.Double:
            case PrimitiveTypeCode.Decimal:
                return(schemaType | JSchemaType.Number);

            case PrimitiveTypeCode.DateTime:
            case PrimitiveTypeCode.DateTimeOffset:
                return(schemaType | JSchemaType.String);

            case PrimitiveTypeCode.String:
            case PrimitiveTypeCode.Uri:
            case PrimitiveTypeCode.Guid:
            case PrimitiveTypeCode.TimeSpan:
            case PrimitiveTypeCode.Bytes:
                return(schemaType | JSchemaType.String);

            default:
                throw new JSchemaException("Unexpected type code '{0}' for type '{1}'.".FormatWith(CultureInfo.InvariantCulture, typeCode, type));
            }
        }
        private JSchema PopulateSchema(JSchema schema, JsonContract contract, JsonProperty memberProperty, Required valueRequired)
        {
            schema.Title       = GetTitle(contract.NonNullableUnderlyingType);
            schema.Description = GetDescription(contract.NonNullableUnderlyingType);

            JsonConverter converter = contract.Converter ?? contract.InternalConverter;

            if (converter != null)
            {
                // todo: Add GetSchema to JsonConverter and use here?
                schema.Type = JSchemaType.Any;
            }
            else
            {
                switch (contract.ContractType)
                {
                case JsonContractType.Object:
                    if (schema.Id == null)
                    {
                        schema.Id = GetTypeId(contract.NonNullableUnderlyingType, false);
                    }

                    schema.Type = AddNullType(JSchemaType.Object, valueRequired);
                    GenerateObjectSchema(schema, contract.NonNullableUnderlyingType, (JsonObjectContract)contract);
                    break;

                case JsonContractType.Array:
                    if (schema.Id == null)
                    {
                        schema.Id = GetTypeId(contract.NonNullableUnderlyingType, false);
                    }

                    schema.Type         = AddNullType(JSchemaType.Array, valueRequired);
                    schema.MinimumItems = DataAnnotationHelpers.GetMinLength(memberProperty);
                    schema.MaximumItems = DataAnnotationHelpers.GetMaxLength(memberProperty);

                    JsonArrayAttribute arrayAttribute = JsonTypeReflector.GetCachedAttribute <JsonArrayAttribute>(contract.NonNullableUnderlyingType);
                    bool allowNullItem = (arrayAttribute == null || arrayAttribute.AllowNullItems);

                    Type collectionItemType = ReflectionUtils.GetCollectionItemType(contract.NonNullableUnderlyingType);
                    if (collectionItemType != null)
                    {
                        schema.Items.Add(GenerateInternal(collectionItemType, (!allowNullItem) ? Required.Always : Required.Default, null, (JsonArrayContract)contract));
                    }
                    break;

                case JsonContractType.Primitive:
                    schema.Type = GetJSchemaType(contract.UnderlyingType, valueRequired);

                    if (JSchemaTypeHelpers.HasFlag(schema.Type, JSchemaType.String))
                    {
                        int minimumLength;
                        int maximumLength;
                        if (DataAnnotationHelpers.GetStringLength(memberProperty, out minimumLength, out maximumLength))
                        {
                            schema.MinimumLength = minimumLength;
                            schema.MaximumLength = maximumLength;
                        }
                        else
                        {
                            schema.MinimumLength = DataAnnotationHelpers.GetMinLength(memberProperty);
                            schema.MaximumLength = DataAnnotationHelpers.GetMaxLength(memberProperty);
                        }

                        schema.Pattern = DataAnnotationHelpers.GetPattern(memberProperty);
                        schema.Format  = DataAnnotationHelpers.GetFormat(memberProperty);
                    }
                    if (JSchemaTypeHelpers.HasFlag(schema.Type, JSchemaType.Float) || JSchemaTypeHelpers.HasFlag(schema.Type, JSchemaType.Integer))
                    {
                        double minimum;
                        double maximum;
                        if (DataAnnotationHelpers.GetRange(memberProperty, out minimum, out maximum))
                        {
                            schema.Minimum = minimum;
                            schema.Maximum = maximum;
                        }
                    }

                    if (JSchemaTypeHelpers.HasFlag(schema.Type, JSchemaType.Integer) &&
                        contract.NonNullableUnderlyingType.IsEnum() &&
                        ReflectionUtils.GetAttribute <FlagsAttribute>(contract.NonNullableUnderlyingType) == null)
                    {
                        IList <EnumValue <long> > enumValues = EnumUtils.GetNamesAndValues <long>(contract.NonNullableUnderlyingType);
                        foreach (EnumValue <long> enumValue in enumValues)
                        {
                            JToken value = JToken.FromObject(enumValue.Value);

                            schema.Enum.Add(value);
                        }
                    }

                    Type enumDataType = DataAnnotationHelpers.GetEnumDataType(memberProperty);
                    if (enumDataType != null && CollectionUtils.IsNullOrEmpty(schema._enum))
                    {
                        IList <EnumValue <long> > enumValues = EnumUtils.GetNamesAndValues <long>(enumDataType);
                        foreach (EnumValue <long> enumValue in enumValues)
                        {
                            JToken value = (JSchemaTypeHelpers.HasFlag(schema.Type, JSchemaType.String))
                                    ? enumValue.Name
                                    : JToken.FromObject(enumValue.Value);

                            schema.Enum.Add(value);
                        }
                    }
                    break;

                case JsonContractType.String:
                    JSchemaType schemaType = (!ReflectionUtils.IsNullable(contract.UnderlyingType))
                            ? JSchemaType.String
                            : AddNullType(JSchemaType.String, valueRequired);

                    schema.Type          = schemaType;
                    schema.MinimumLength = DataAnnotationHelpers.GetMinLength(memberProperty);
                    schema.MaximumLength = DataAnnotationHelpers.GetMaxLength(memberProperty);
                    break;

                case JsonContractType.Dictionary:
                    schema.Type = AddNullType(JSchemaType.Object, valueRequired);
                    schema.MinimumProperties = DataAnnotationHelpers.GetMinLength(memberProperty);
                    schema.MaximumProperties = DataAnnotationHelpers.GetMaxLength(memberProperty);

                    Type keyType;
                    Type valueType;
                    ReflectionUtils.GetDictionaryKeyValueTypes(contract.NonNullableUnderlyingType, out keyType, out valueType);

                    if (keyType != null)
                    {
                        JsonContract keyContract = ContractResolver.ResolveContract(keyType);

                        // can be converted to a string
                        if (keyContract.ContractType == JsonContractType.Primitive)
                        {
                            schema.AdditionalProperties = GenerateInternal(valueType, Required.Default, null, (JsonDictionaryContract)contract);
                        }
                    }
                    break;

                case JsonContractType.Serializable:
                    if (schema.Id == null)
                    {
                        schema.Id = GetTypeId(contract.NonNullableUnderlyingType, false);
                    }

                    schema.Type = AddNullType(JSchemaType.Object, valueRequired);
                    schema.AllowAdditionalProperties = true;
                    break;

                case JsonContractType.Dynamic:
                case JsonContractType.Linq:
                    schema.Type = JSchemaType.Any;
                    break;

                default:
                    throw new JsonException("Unexpected contract type: {0}".FormatWith(CultureInfo.InvariantCulture, contract));
                }
            }

            return(schema);
        }
Exemple #14
0
        private object ReadType(JsonReader reader, string name)
        {
            EnsureRead(reader, name);

            List <JSchemaType> types       = new List <JSchemaType>();
            List <JSchema>     typeSchemas = null;

            switch (reader.TokenType)
            {
            case JsonToken.String:
                return(JSchemaTypeHelpers.MapType((string)reader.Value));

            case JsonToken.StartArray:
                while (reader.Read())
                {
                    switch (reader.TokenType)
                    {
                    case JsonToken.String:
                        JSchemaType t = JSchemaTypeHelpers.MapType((string)reader.Value);
                        if (typeSchemas != null)
                        {
                            typeSchemas.Add(new JSchema {
                                Type = t
                            });
                        }
                        else
                        {
                            types.Add(t);
                        }
                        break;

                    case JsonToken.StartObject:
                        if (typeSchemas == null)
                        {
                            typeSchemas = new List <JSchema>();
                            foreach (JSchemaType type in types)
                            {
                                typeSchemas.Add(new JSchema
                                {
                                    Type = type
                                });
                            }
                            types = null;
                        }
                        int            count = typeSchemas.Count;
                        List <JSchema> l     = typeSchemas;
                        LoadAndSetSchema(reader, s => SetAtIndex(l, count, s));
                        break;

                    case JsonToken.Comment:
                        // nom nom nom
                        break;

                    case JsonToken.EndArray:
                        if (typeSchemas != null)
                        {
                            return(typeSchemas);
                        }

                        JSchemaType finalType = JSchemaType.None;
                        foreach (JSchemaType type in types)
                        {
                            finalType = finalType | type;
                        }

                        return(finalType);

                    default:
                        throw JsonException.Create(reader as IJsonLineInfo, reader.Path, "Expected string token for type, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
                    }
                }
                break;

            default:
                throw JsonException.Create(null, reader.Path, "Expected array or string for '{0}', got {1}.".FormatWith(CultureInfo.InvariantCulture, Constants.PropertyNames.Type, reader.TokenType));
            }

            throw JsonReaderException.Create(reader, "Unexpected end when reading schema type.");
        }
 public void IgnoreNonEnumSchema(JSchemaType type)
 {
     Sut.EnsureIgnore(new JSchema {
         Type = type
     });
 }
        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);
        }
Exemple #17
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
        protected bool TestType(JSchema currentSchema, JSchemaType currentType, object value)
        {
            if (!JSchemaTypeHelpers.HasFlag(currentSchema.Type, currentType))
            {
                RaiseError($"Invalid type. Expected {currentSchema.Type} but got {currentType}.", ErrorType.Type, currentSchema, value, null);
                return false;
            }

            return true;
        }
Exemple #19
0
 public void IgnoreNonBase64Schema(JSchemaType type, string format = null)
 {
     new Base64Provider().EnsureIgnore(new JSchema {
         Type = type, Format = format
     });
 }
Exemple #20
0
        private void PopulateSchema(JSchema schema, JsonContract contract, JsonProperty memberProperty, Required valueRequired)
        {
            Type nonNullableUnderlyingType = GetNonNullableUnderlyingType(contract);

            schema.Title       = GetTitle(nonNullableUnderlyingType, memberProperty);
            schema.Description = GetDescription(nonNullableUnderlyingType, memberProperty);

            JsonConverter converter;

            if (contract.Converter != null && contract.Converter.CanWrite)
            {
                converter = contract.Converter;
            }
            else if (contract.InternalConverter != null && contract.InternalConverter.CanWrite)
            {
                converter = contract.InternalConverter;
            }
            else
            {
                converter = null;
            }

            if (converter != null)
            {
                schema.Type = null;
            }
            else
            {
                switch (contract)
                {
                case JsonObjectContract objectContract:
                    if (nonNullableUnderlyingType == typeof(object))
                    {
                        PopulatePrimativeSchema(schema, objectContract, memberProperty, valueRequired);
                    }
                    else
                    {
                        if (schema.Id == null)
                        {
                            schema.Id = GetTypeId(nonNullableUnderlyingType, false);
                        }

                        schema.Type = AddNullType(JSchemaType.Object, valueRequired);
                        GenerateObjectSchema(schema, nonNullableUnderlyingType, objectContract);
                    }
                    break;

                case JsonArrayContract arrayContract:
                    if (schema.Id == null)
                    {
                        schema.Id = GetTypeId(nonNullableUnderlyingType, false);
                    }

                    schema.Type         = AddNullType(JSchemaType.Array, valueRequired);
                    schema.MinimumItems = AttributeHelpers.GetMinLength(memberProperty);
                    schema.MaximumItems = AttributeHelpers.GetMaxLength(memberProperty);

                    JsonArrayAttribute arrayAttribute = ReflectionUtils.GetAttribute <JsonArrayAttribute>(nonNullableUnderlyingType);

                    Required?required = null;
                    if (arrayAttribute != null && !arrayAttribute.AllowNullItems)
                    {
                        required = Required.Always;
                    }

                    Type collectionItemType = ReflectionUtils.GetCollectionItemType(nonNullableUnderlyingType);
                    if (collectionItemType != null)
                    {
                        schema.Items.Add(GenerateInternal(collectionItemType, required, null, arrayContract, null));
                    }
                    break;

                case JsonStringContract stringContract:
                    JSchemaType schemaType = (!ReflectionUtils.IsNullable(stringContract.UnderlyingType))
                            ? JSchemaType.String
                            : AddNullType(JSchemaType.String, valueRequired);

                    schema.Type          = schemaType;
                    schema.MinimumLength = AttributeHelpers.GetMinLength(memberProperty);
                    schema.MaximumLength = AttributeHelpers.GetMaxLength(memberProperty);
                    break;

                case JsonPrimitiveContract primitiveContract:
                    PopulatePrimativeSchema(schema, primitiveContract, memberProperty, valueRequired);
                    break;

                case JsonDictionaryContract dictionaryContract:
                    schema.Type = AddNullType(JSchemaType.Object, valueRequired);
                    schema.MinimumProperties = AttributeHelpers.GetMinLength(memberProperty);
                    schema.MaximumProperties = AttributeHelpers.GetMaxLength(memberProperty);

                    ReflectionUtils.GetDictionaryKeyValueTypes(nonNullableUnderlyingType, out Type keyType, out Type valueType);

                    if (keyType != null)
                    {
                        JsonContract keyContract = _generator.ContractResolver.ResolveContract(keyType);

                        // can be converted to a string
                        if (keyContract is JsonPrimitiveContract)
                        {
                            schema.AdditionalProperties = GenerateInternal(valueType, _generator.DefaultRequired, null, dictionaryContract, null);
                        }
                    }
                    break;

#if !PORTABLE || NETSTANDARD1_3 || NETSTANDARD2_0
                case JsonISerializableContract serializableContract:
                    if (schema.Id == null)
                    {
                        schema.Id = GetTypeId(nonNullableUnderlyingType, false);
                    }

                    schema.Type = AddNullType(JSchemaType.Object, valueRequired);
                    schema.AllowAdditionalProperties = true;
                    break;
#endif
#if !NET35
                case JsonDynamicContract dynamicContract:
#endif
                case JsonLinqContract linqContract:
                    schema.Type = null;
                    break;

                default:
                    throw new JSchemaException("Unexpected contract type: {0}".FormatWith(CultureInfo.InvariantCulture, contract));
                }
            }
        }
Exemple #21
0
 private static bool HasThisAndOthers(JSchemaType type, JSchemaType schemaType)
 {
     return(type != schemaType && type.HasFlag(schemaType));
 }
Exemple #22
0
 public void IgnoreNonArraySchemas(JSchemaType type)
 {
     Sut(null).EnsureIgnore(new JSchema {
         Type = type
     });
 }
Exemple #23
0
        private void ProcessSchemaName(JsonReader reader, JSchema schema, string name)
        {
            switch (name)
            {
            case Constants.PropertyNames.Id:
                schema.Id = ReadUri(reader, name);
                break;

            case Constants.PropertyNames.Ref:
                schema.Reference = ReadUri(reader, name);
                break;

            case Constants.PropertyNames.Properties:
                schema._properties = ReadProperties(reader);

                // add schemas with deprecated required flag to new required array
                foreach (KeyValuePair <string, JSchema> schemaProperty in schema.Properties)
                {
                    if (schemaProperty.Value.DeprecatedRequired)
                    {
                        if (!schema.Required.Contains(schemaProperty.Key))
                        {
                            schema.Required.Add(schemaProperty.Key);
                        }
                    }
                }
                break;

            case Constants.PropertyNames.Items:
                ReadItems(reader, schema);
                break;

            case Constants.PropertyNames.Type:
            {
                object typeResult = ReadType(reader, name);
                if (typeResult is JSchemaType)
                {
                    schema.Type = (JSchemaType)typeResult;
                }
                else
                {
                    schema._anyOf = (List <JSchema>)typeResult;
                }
                break;
            }

            case Constants.PropertyNames.AnyOf:
                ReadSchemaArray(reader, name, out schema._anyOf);
                break;

            case Constants.PropertyNames.AllOf:
                ReadSchemaArray(reader, name, out schema._allOf);
                break;

            case Constants.PropertyNames.OneOf:
                ReadSchemaArray(reader, name, out schema._oneOf);
                break;

            case Constants.PropertyNames.Not:
                ReadSchema(reader, name, s => schema.Not = s);
                break;

            case Constants.PropertyNames.Title:
                schema.Title = ReadString(reader, name);
                break;

            case Constants.PropertyNames.Description:
                schema.Description = ReadString(reader, name);
                break;

            case Constants.PropertyNames.Format:
                schema.Format = ReadString(reader, name);
                break;

            case Constants.PropertyNames.AdditionalProperties:
                ReadAdditionalProperties(reader, schema);
                break;

            case Constants.PropertyNames.AdditionalItems:
                ReadAdditionalItems(reader, schema);
                break;

            case Constants.PropertyNames.PatternProperties:
                schema._patternProperties = ReadProperties(reader);
                break;

            case Constants.PropertyNames.Required:
                ReadRequired(reader, schema);
                break;

            case Constants.PropertyNames.Dependencies:
                ReadDependencies(reader, schema);
                break;

            case Constants.PropertyNames.Minimum:
                schema.Minimum = ReadDouble(reader, name);
                break;

            case Constants.PropertyNames.Maximum:
                schema.Maximum = ReadDouble(reader, name);
                break;

            case Constants.PropertyNames.ExclusiveMinimum:
                schema.ExclusiveMinimum = ReadBoolean(reader, name);
                break;

            case Constants.PropertyNames.ExclusiveMaximum:
                schema.ExclusiveMaximum = ReadBoolean(reader, name);
                break;

            case Constants.PropertyNames.MaximumLength:
                schema.MaximumLength = ReadInteger(reader, name);
                break;

            case Constants.PropertyNames.MinimumLength:
                schema.MinimumLength = ReadInteger(reader, name);
                break;

            case Constants.PropertyNames.MaximumItems:
                schema.MaximumItems = ReadInteger(reader, name);
                break;

            case Constants.PropertyNames.MinimumItems:
                schema.MinimumItems = ReadInteger(reader, name);
                break;

            case Constants.PropertyNames.MaximumProperties:
                schema.MaximumProperties = ReadInteger(reader, name);
                break;

            case Constants.PropertyNames.MinimumProperties:
                schema.MinimumProperties = ReadInteger(reader, name);
                break;

            case Constants.PropertyNames.DivisibleBy:
            case Constants.PropertyNames.MultipleOf:
                schema.MultipleOf = ReadDouble(reader, name);
                break;

            case Constants.PropertyNames.Disallow:
            {
                if (schema.Not == null)
                {
                    schema.Not = new JSchema();
                }

                object disallowResult = ReadType(reader, name);
                if (disallowResult is JSchemaType)
                {
                    JSchemaType type = schema.Not.Type ?? JSchemaType.None;
                    schema.Not.Type = type | (JSchemaType)disallowResult;
                }
                else
                {
                    schema.Not._anyOf = (List <JSchema>)disallowResult;
                }
                break;
            }

            case Constants.PropertyNames.Pattern:
                schema.Pattern = ReadString(reader, name);
                break;

            case Constants.PropertyNames.Enum:
                ReadTokenArray(reader, name, ref schema._enum);
                if (schema._enum.Count == 0)
                {
                    throw new JsonException("Enum array must have at least one value.");
                }
                break;

            case Constants.PropertyNames.Extends:
                ReadExtends(reader, schema);
                break;

            case Constants.PropertyNames.UniqueItems:
                schema.UniqueItems = ReadBoolean(reader, name);
                break;

            case Constants.PropertyNames.Default:
                EnsureRead(reader, Constants.PropertyNames.Default);
                schema.Default = JToken.ReadFrom(reader);
                break;

            default:
                if (!reader.Read())
                {
                    throw JsonReaderException.Create(reader, "Unexpected end when reading schema.");
                }

                JToken t;
                if (reader is JTokenReader)
                {
                    t = ((JTokenReader)reader).CurrentToken;
                    reader.Skip();
                }
                else
                {
                    t = JToken.ReadFrom(reader);
                }

                schema.ExtensionData[name] = t;
                break;
            }
        }
 internal static string MapType(JSchemaType type)
 {
     return Constants.JSchemaTypeMapping.Single(kv => kv.Value == type).Key;
 }
 public static string GetDisplayText(this JSchemaType value)
 {
     return(CachedSchemaTypeNames[value]);
 }
        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);
        }
Exemple #27
0
        private Type JSchemaType2Type(JSchema schema)
        {
            if (schema?.Type == null)
            {
                return(null);
            }

            JSchemaType s = schema.Type.Value;

            if (IsSet(s, JSchemaType.Null))
            {
                //nullable types
                if (IsSet(s, JSchemaType.String))
                {
                    if (schema.Format == "date-time")
                    {
                        return(typeof(Nullable <DateTime>));
                    }
                    else if (schema.Format == "date")
                    {
                        return(typeof(Nullable <Date>));
                    }
                    else
                    {
                        return(typeof(string));
                    }
                }
                else if (IsSet(s, JSchemaType.Number))
                {
                    return(typeof(Nullable <decimal>));
                }
                else if (IsSet(s, JSchemaType.Integer))
                {
                    return(typeof(Nullable <long>));
                }
                else if (IsSet(s, JSchemaType.Boolean))
                {
                    return(typeof(Nullable <bool>));
                }
                else if (IsSet(s, JSchemaType.Object))
                {
                    return(typeof(object));
                }
                else if (IsSet(s, JSchemaType.Array))
                {
                    return(typeof(object[]));
                }
                else if (IsSet(s, JSchemaType.None))
                {
                    return(null);
                }
                else
                {
                    return(null);
                }
            }
            else
            {
                if (IsSet(s, JSchemaType.String))
                {
                    if (schema.Format == "date" || schema.Format == "date-time")
                    {
                        return(typeof(DateTime));
                    }
                    else if (schema.Format == "date")
                    {
                        return(typeof(Date));
                    }
                    else
                    {
                        return(typeof(string));
                    }
                }
                else if (IsSet(s, JSchemaType.Number))
                {
                    return(typeof(decimal));
                }
                else if (IsSet(s, JSchemaType.Integer))
                {
                    return(typeof(long));
                }
                else if (IsSet(s, JSchemaType.Boolean))
                {
                    return(typeof(bool));
                }
                else if (IsSet(s, JSchemaType.Object))
                {
                    return(typeof(object));
                }
                else if (IsSet(s, JSchemaType.Array))
                {
                    return(typeof(object[]));
                }
                else if (IsSet(s, JSchemaType.None))
                {
                    return(null);
                }
                else
                {
                    return(null);
                }
            }
        }
Exemple #28
0
 protected bool TestType <T>(JSchema currentSchema, JSchemaType currentType, T value)
 {
     return(TestType(this, currentSchema, currentType, value));
 }
        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);
        }
 internal static string MapType(JSchemaType type)
 {
     return(Constants.JSchemaTypeMapping.Single(kv => kv.Value == type).Key);
 }
 /// <summary>
 /// Returns an expression that returns <c>true</c> if the specified expression is compatible with the given schema type.
 /// </summary>
 /// <param name="o"></param>
 /// <param name="t"></param>
 /// <returns></returns>
 static Expression IsSchemaType(JSchema schema, Expression o, JSchemaType t) =>
 CallThis(nameof(IsSchemaTypeFunc), Expression.Constant(schema), o, Expression.Constant(t));
        private void PopulatePrimativeSchema(JSchema schema, JsonContract contract, JsonProperty memberProperty, Required valueRequired)
        {
            JSchemaType type = GetJSchemaType(contract.UnderlyingType, valueRequired);

            if (type != Constants.AnyType)
            {
                schema.Type = GetJSchemaType(contract.UnderlyingType, valueRequired);
            }

            if (JSchemaTypeHelpers.HasFlag(schema.Type, JSchemaType.String))
            {
                int minimumLength;
                int maximumLength;
                if (DataAnnotationHelpers.GetStringLength(memberProperty, out minimumLength, out maximumLength))
                {
                    schema.MinimumLength = minimumLength;
                    schema.MaximumLength = maximumLength;
                }
                else
                {
                    schema.MinimumLength = DataAnnotationHelpers.GetMinLength(memberProperty);
                    schema.MaximumLength = DataAnnotationHelpers.GetMaxLength(memberProperty);
                }

                schema.Pattern = DataAnnotationHelpers.GetPattern(memberProperty);
                schema.Format  = DataAnnotationHelpers.GetFormat(memberProperty);
            }
            if (JSchemaTypeHelpers.HasFlag(type, JSchemaType.Number) || JSchemaTypeHelpers.HasFlag(type, JSchemaType.Integer))
            {
                double minimum;
                double maximum;
                if (DataAnnotationHelpers.GetRange(memberProperty, out minimum, out maximum))
                {
                    schema.Minimum = minimum;
                    schema.Maximum = maximum;
                }
            }

            if (JSchemaTypeHelpers.HasFlag(type, JSchemaType.Integer) &&
                contract.NonNullableUnderlyingType.IsEnum() &&
                ReflectionUtils.GetAttribute <FlagsAttribute>(contract.NonNullableUnderlyingType) == null)
            {
                if ((type & JSchemaType.Null) == JSchemaType.Null)
                {
                    schema.Enum.Add(JValue.CreateNull());
                }

                IList <EnumValue <long> > enumValues = EnumUtils.GetNamesAndValues <long>(contract.NonNullableUnderlyingType);
                foreach (EnumValue <long> enumValue in enumValues)
                {
                    JToken value = JToken.FromObject(enumValue.Value);

                    schema.Enum.Add(value);
                }
            }

            Type enumDataType = DataAnnotationHelpers.GetEnumDataType(memberProperty);

            if (enumDataType != null && CollectionUtils.IsNullOrEmpty(schema._enum))
            {
                IList <EnumValue <long> > enumValues = EnumUtils.GetNamesAndValues <long>(enumDataType);
                foreach (EnumValue <long> enumValue in enumValues)
                {
                    JToken value = (JSchemaTypeHelpers.HasFlag(type, JSchemaType.String))
                        ? enumValue.Name
                        : JToken.FromObject(enumValue.Value);

                    schema.Enum.Add(value);
                }
            }
        }
        private JSchemaType AddNullType(JSchemaType type, Required valueRequired)
        {
            if (valueRequired == Required.Default || valueRequired == Required.AllowNull)
            {
                return type | JSchemaType.Null;
            }

            return type;
        }
        private JSchemaType AddNullType(JSchemaType type, Required valueRequired)
        {
            if (valueRequired != Required.Always)
                return type | JSchemaType.Null;

            return type;
        }
Exemple #35
0
        private object ReadType(JsonReader reader, string name)
        {
            EnsureRead(reader, name);

            List <JSchemaType> types       = new List <JSchemaType>();
            List <JSchema>     typeSchemas = null;
            bool isAny = false;

            switch (reader.TokenType)
            {
            case JsonToken.String:
                return(MapType(reader));

            case JsonToken.StartArray:
                while (reader.Read())
                {
                    switch (reader.TokenType)
                    {
                    case JsonToken.String:
                        JSchemaType?t = MapType(reader);

                        if (t == null)
                        {
                            isAny = true;
                        }
                        else
                        {
                            if (typeSchemas != null)
                            {
                                typeSchemas.Add(new JSchema {
                                    Type = t
                                });
                            }
                            else
                            {
                                types.Add(t.Value);
                            }
                        }
                        break;

                    case JsonToken.Comment:
                        // nom nom nom
                        break;

                    case JsonToken.EndArray:
                        // type of "any" removes all other type constraints
                        if (isAny)
                        {
                            return(null);
                        }

                        if (typeSchemas != null)
                        {
                            return(typeSchemas);
                        }

                        JSchemaType finalType = JSchemaType.None;
                        foreach (JSchemaType type in types)
                        {
                            finalType = finalType | type;
                        }

                        return(finalType);

                    default:
                        if (EnsureVersion(SchemaVersion.Draft3, SchemaVersion.Draft3))
                        {
                            if (typeSchemas == null)
                            {
                                typeSchemas = new List <JSchema>();
                                foreach (JSchemaType type in types)
                                {
                                    typeSchemas.Add(new JSchema
                                    {
                                        Type = type
                                    });
                                }
                                types = null;
                            }
                            int            count = typeSchemas.Count;
                            List <JSchema> l     = typeSchemas;
                            LoadAndSetSchema(reader, s => SetAtIndex(l, count, s));
                        }
                        else
                        {
                            throw JSchemaReaderException.Create(reader, _baseUri, "Expected string token for type, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
                        }
                        break;
                    }
                }
                break;

            default:
                throw JSchemaReaderException.Create(reader, _baseUri, "Expected array or string for '{0}', got {1}.".FormatWith(CultureInfo.InvariantCulture, Constants.PropertyNames.Type, reader.TokenType));
            }

            throw JSchemaReaderException.Create(reader, _baseUri, "Unexpected end when reading schema type.");
        }
Exemple #36
0
 protected bool TestType(JSchema currentSchema, JSchemaType currentType)
 {
     return(TestType <object>(currentSchema, currentType, null));
 }
Exemple #37
0
        private void ProcessSchemaName(ref JsonReader reader, bool isRoot, JSchema schema, string name)
        {
            switch (name)
            {
            case Constants.PropertyNames.Id:
                schema.Id = ReadUri(reader, name);
                break;

            case Constants.PropertyNames.Ref:
                schema.Reference = ReadUri(reader, name);
                break;

            case Constants.PropertyNames.Properties:
                schema._properties = ReadProperties(reader);

                // add schemas with deprecated required flag to new required array
                foreach (KeyValuePair <string, JSchema> schemaProperty in schema.Properties)
                {
                    if (schemaProperty.Value.DeprecatedRequired)
                    {
                        if (!schema.Required.Contains(schemaProperty.Key))
                        {
                            schema.Required.Add(schemaProperty.Key);
                        }
                    }
                }
                break;

            case Constants.PropertyNames.Items:
                ReadItems(reader, schema);
                break;

            case Constants.PropertyNames.Type:
            {
                object typeResult = ReadType(reader, name);
                if (typeResult is JSchemaType)
                {
                    schema.Type = (JSchemaType)typeResult;
                }
                else
                {
                    schema._anyOf = (List <JSchema>)typeResult;
                }
                break;
            }

            case Constants.PropertyNames.AnyOf:
                if (EnsureVersion(SchemaVersion.Draft4))
                {
                    ReadSchemaArray(reader, name, out schema._anyOf);
                }
                else
                {
                    ReadExtensionData(reader, schema, name);
                }
                break;

            case Constants.PropertyNames.AllOf:
                if (EnsureVersion(SchemaVersion.Draft4))
                {
                    ReadSchemaArray(reader, name, out schema._allOf);
                }
                else
                {
                    ReadExtensionData(reader, schema, name);
                }
                break;

            case Constants.PropertyNames.OneOf:
                if (EnsureVersion(SchemaVersion.Draft4))
                {
                    ReadSchemaArray(reader, name, out schema._oneOf);
                }
                else
                {
                    ReadExtensionData(reader, schema, name);
                }
                break;

            case Constants.PropertyNames.Not:
                if (EnsureVersion(SchemaVersion.Draft4))
                {
                    ReadSchema(reader, name, s => schema.Not = s);
                }
                else
                {
                    ReadExtensionData(reader, schema, name);
                }
                break;

            case Constants.PropertyNames.Title:
                schema.Title = ReadString(reader, name);
                break;

            case Constants.PropertyNames.Description:
                schema.Description = ReadString(reader, name);
                break;

            case Constants.PropertyNames.Format:
                schema.Format = ReadString(reader, name);
                break;

            case Constants.PropertyNames.AdditionalProperties:
                ReadAdditionalProperties(reader, schema);
                break;

            case Constants.PropertyNames.AdditionalItems:
                ReadAdditionalItems(reader, schema);
                break;

            case Constants.PropertyNames.PatternProperties:
                schema._patternProperties = ReadProperties(reader);
                break;

            case Constants.PropertyNames.Required:
                ReadRequired(reader, schema);
                break;

            case Constants.PropertyNames.Dependencies:
                ReadDependencies(reader, schema);
                break;

            case Constants.PropertyNames.Minimum:
                schema.Minimum = ReadDouble(reader, name);
                break;

            case Constants.PropertyNames.Maximum:
                schema.Maximum = ReadDouble(reader, name);
                break;

            case Constants.PropertyNames.ExclusiveMinimum:
                schema.ExclusiveMinimum = ReadBoolean(reader, name);
                break;

            case Constants.PropertyNames.ExclusiveMaximum:
                schema.ExclusiveMaximum = ReadBoolean(reader, name);
                break;

            case Constants.PropertyNames.MaximumLength:
                schema.MaximumLength = ReadInteger(reader, name);
                break;

            case Constants.PropertyNames.MinimumLength:
                schema.MinimumLength = ReadInteger(reader, name);
                break;

            case Constants.PropertyNames.MaximumItems:
                schema.MaximumItems = ReadInteger(reader, name);
                break;

            case Constants.PropertyNames.MinimumItems:
                schema.MinimumItems = ReadInteger(reader, name);
                break;

            case Constants.PropertyNames.MaximumProperties:
                if (EnsureVersion(SchemaVersion.Draft4))
                {
                    schema.MaximumProperties = ReadInteger(reader, name);
                }
                else
                {
                    ReadExtensionData(reader, schema, name);
                }
                break;

            case Constants.PropertyNames.MinimumProperties:
                if (EnsureVersion(SchemaVersion.Draft4))
                {
                    schema.MinimumProperties = ReadInteger(reader, name);
                }
                else
                {
                    ReadExtensionData(reader, schema, name);
                }
                break;

            case Constants.PropertyNames.DivisibleBy:
                if (EnsureVersion(SchemaVersion.Draft3, SchemaVersion.Draft3))
                {
                    schema.MultipleOf = ReadDouble(reader, name);
                }
                else
                {
                    ReadExtensionData(reader, schema, name);
                }
                break;

            case Constants.PropertyNames.MultipleOf:
                if (EnsureVersion(SchemaVersion.Draft4))
                {
                    schema.MultipleOf = ReadDouble(reader, name);
                }
                else
                {
                    ReadExtensionData(reader, schema, name);
                }
                break;

            case Constants.PropertyNames.Disallow:
            {
                if (EnsureVersion(SchemaVersion.Draft3, SchemaVersion.Draft3))
                {
                    if (schema.Not == null)
                    {
                        schema.Not = new JSchema();
                    }

                    object disallowResult = ReadType(reader, name);
                    if (disallowResult is JSchemaType)
                    {
                        JSchemaType type = schema.Not.Type ?? JSchemaType.None;
                        schema.Not.Type = type | (JSchemaType)disallowResult;
                    }
                    else
                    {
                        schema.Not._anyOf = (List <JSchema>)disallowResult;
                    }
                }
                else
                {
                    ReadExtensionData(reader, schema, name);
                }
                break;
            }

            case Constants.PropertyNames.Pattern:
                schema.Pattern = ReadString(reader, name);

                if (_validationErrors != null)
                {
                    Regex  patternRegex;
                    string errorMessage;
                    if (!schema.TryGetPatternRegex(out patternRegex, out errorMessage))
                    {
                        ValidationError error = ValidationError.CreateValidationError("Could not parse regex pattern '{0}'. Regex parser error: {1}".FormatWith(CultureInfo.InvariantCulture, schema.Pattern, errorMessage), ErrorType.Pattern, schema, null, schema.Pattern, null, schema, schema.Path);
                        _validationErrors.Add(error);
                    }
                }
                break;

            case Constants.PropertyNames.Enum:
                ReadTokenArray(reader, name, ref schema._enum);
                if (schema._enum.Count == 0)
                {
                    throw JSchemaReaderException.Create(reader, _baseUri, "Enum array must have at least one value.");
                }
                break;

            case Constants.PropertyNames.Extends:
                if (EnsureVersion(SchemaVersion.Draft3, SchemaVersion.Draft3))
                {
                    ReadExtends(reader, schema);
                }
                else
                {
                    ReadExtensionData(reader, schema, name);
                }
                break;

            case Constants.PropertyNames.UniqueItems:
                schema.UniqueItems = ReadBoolean(reader, name);
                break;

            case Constants.PropertyNames.Default:
                EnsureRead(reader, Constants.PropertyNames.Default);
                schema.Default = JToken.ReadFrom(reader);
                break;

            default:
                if (isRoot && name == Constants.PropertyNames.Schema)
                {
                    if (!reader.Read())
                    {
                        throw JSchemaReaderException.Create(reader, _baseUri, "Unexpected end when reading schema.");
                    }

                    if (reader.TokenType != JsonToken.String)
                    {
                        throw JSchemaReaderException.Create(reader, _baseUri, "Unexpected token encountered when reading value for '$schema'. Expected String, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
                    }

                    _schemaVersionUri = new Uri((string)reader.Value, UriKind.RelativeOrAbsolute);

#if !PORTABLE
                    string tempUriText = _schemaVersionUri.OriginalString.ToLower(CultureInfo.InvariantCulture);
#else
                    string tempUriText = _schemaVersionUri.OriginalString.ToLower();
#endif

                    Uri tempUri = new Uri(tempUriText, UriKind.RelativeOrAbsolute);
                    if (tempUri == Constants.SchemaVersions.Draft3)
                    {
                        _schemaVersion = SchemaVersion.Draft3;
                    }
                    else if (tempUri == Constants.SchemaVersions.Draft4)
                    {
                        _schemaVersion = SchemaVersion.Draft4;
                    }

                    if (_validateSchema)
                    {
                        if (_schemaVersion == SchemaVersion.Draft3)
                        {
                            _validatingSchema = SpecSchemaCache.Get("schema-draft-v3.json");
                        }
                        else if (_schemaVersion == SchemaVersion.Draft4)
                        {
                            _validatingSchema = SpecSchemaCache.Get("schema-draft-v4.json");
                        }
                        else
                        {
                            if (!_schemaVersionUri.IsAbsoluteUri)
                            {
                                throw JSchemaReaderException.Create(reader, _baseUri, "Schema version identifier '{0}' is not an absolute URI.".FormatWith(CultureInfo.InvariantCulture, _schemaVersionUri.OriginalString));
                            }

                            _validatingSchema = ResolvedSchema(_schemaVersionUri, _schemaVersionUri);

                            if (_validatingSchema == null)
                            {
                                throw JSchemaReaderException.Create(reader, _baseUri, "Could not resolve schema version identifier '{0}'.".FormatWith(CultureInfo.InvariantCulture, _schemaVersionUri.OriginalString));
                            }
                        }

                        JSchemaValidatingReader validatingReader = new JSchemaValidatingReader(reader);
                        validatingReader.Schema = _validatingSchema;
                        // push state that we're already inside an object
                        validatingReader.Validator.ValidateCurrentToken(JsonToken.StartObject, null, 0);
                        validatingReader.ValidationEventHandler += RaiseSchemaValidationError;

                        reader = validatingReader;
                    }
                }
                else
                {
                    ReadExtensionData(reader, schema, name);
                }
                break;
            }
        }