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); }
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); } }
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)); } } }
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(); }
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); } } }
public void IgnoreNonDateTimeSchema(JSchemaType type, string format = null) { Sut.EnsureIgnore(new JSchema { Type = type, Format = format }); }
protected override bool EvaluateTokenCore(JsonToken token, object value, int depth) { switch (token) { case JsonToken.Integer: { if (!ValidateInteger(Schema, value)) { return(true); } break; } case JsonToken.Float: { if (!ValidateNumber(Schema, value)) { return(true); } break; } case JsonToken.String: { Uri uri = value as Uri; string s = (uri != null) ? uri.OriginalString : value.ToString(); if (!ValidateString(Schema, s)) { return(true); } break; } case JsonToken.Boolean: { if (!ValidateBoolean(Schema, value)) { return(true); } break; } case JsonToken.Null: { if (!ValidateNull(Schema, value)) { return(true); } break; } case JsonToken.Bytes: { byte[] data = value as byte[]; if (data == null) { data = ((Guid)value).ToByteArray(); } string s = Convert.ToBase64String(data); if (!ValidateString(Schema, s)) { return(true); } break; } case JsonToken.Undefined: { JSchemaType schemaType = Schema.Type.GetValueOrDefault(JSchemaType.None); if (schemaType != JSchemaType.None) { RaiseError($"Invalid type. Expected {schemaType.GetDisplayText()} but got {token}.", ErrorType.Type, Schema, value, null); } break; } default: { throw new ArgumentOutOfRangeException("Unexpected token: " + token); } } EnsureEnum(token, value); return(true); }
protected override bool EvaluateTokenCore(JsonToken token, object value, int depth) { int relativeDepth = depth - InitialDepth; if (relativeDepth == 0) { EnsureEnum(token, value); switch (token) { case JsonToken.StartArray: 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); }
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); }
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; }
public void IgnoreNonBase64Schema(JSchemaType type, string format = null) { new Base64Provider().EnsureIgnore(new JSchema { Type = type, Format = format }); }
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)); } } }
private static bool HasThisAndOthers(JSchemaType type, JSchemaType schemaType) { return(type != schemaType && type.HasFlag(schemaType)); }
public void IgnoreNonArraySchemas(JSchemaType type) { Sut(null).EnsureIgnore(new JSchema { Type = type }); }
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); }
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); } } }
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; }
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."); }
protected bool TestType(JSchema currentSchema, JSchemaType currentType) { return(TestType <object>(currentSchema, currentType, null)); }
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; } }